## average hashを作成

```<?php
// Average Hashを調べるライブラリ
function makeAHash(\$file, \$cache = TRUE){
\$hashfile = preg_replace('/\.(jpg|jpeg)\$/', '.hash', \$file);
if(\$cach) {
if (file_exists(\$hashfile)){
\$v = file_get_contents(\$hashfile);
return \$v;
}
}
// (1) 16x16にリサイズ
\$sz = 16;
\$src = imagecreatefromjpeg(\$file);
\$sx = imagesx(\$src); \$sy = imagesy(\$src);
\$des = imagecreatetruecolor(\$sz, \$sz);
imagecopyresized(\$des, \$src, 0, 0, 0, 0, \$sz, \$sz, \$sx, \$sy);
imagefilter(\$des, IMG_FILTER_GRAYSCALE);
// (3)平均値を得つつ、配列に入れておく
\$pix = &#91;&#93;; \$sum = 0;
for (\$y = 0; \$y < \$sz; \$y++){
for (\$x = 0; \$x < \$sz; \$x++){
\$rgb = imagecolorat(\$des, \$x, \$y);
\$b = \$rgb & 0xFF;
\$sum += \$b;
\$pix&#91;&#93; = \$b;
}
}
\$ave = floor(\$sum / (\$sz * \$sz));
// (4)2値化する
\$hash = '';
foreach (\$pix as \$i => \$v){
\$hash .= (\$v >= \$ave) ? '1' : '0';
if (\$i % 16 == 15) \$hash .= "\n";
}
}

function enumJpeg(\$path){
\$files = [];
\$fs = scandir(\$path);
foreach (\$fs as \$f){
if (substr(\$f, 0, 1) == ".") continue;
\$fullpath = \$path.'/'.\$f;
if (is_dir(\$fullpath)){
\$files = array_merge(\$files, enumJpeg(\$fullpath));
continue;
}
if (!preg_match('/\.(jpg|jpeg)\$/i', \$f)) continue;
\$files[] = \$fullpath;
}
return \$files;
}```

## ヒストグラム

```<?php
include_one 'histogram-common.inc.php';

define("PHOTO_PATH", "images");

\$up_form = <<< EOS
<h3>類似画像検索</h3>
JPEGファイルを選択してください。<br>
<form enctype="multipart/form-data" method="POST">
<input name="upfile" type="file"><br>
</form></div>
EOS;
\$foot = '</body></html>';

if (empty(\$_FILES['upfile']['tmp_name'])){
exit;
}

\$upfile = dirname(__FILE__).'/upfile.jpg';

\$target = makeHistogram(\$upfile, false);
\$files = enumJpeg(PHOTO_PATH);
\$result = calcIntersection(\$target, \$files);
\$top6 = array_slice(\$result, 0, 6);
echo "<div style='text-align:center'><h2>アップした写真</h2>";
echo "<img src='upfile.jpg' width=300>";
echo "<h2>以下類似する順番に表示</h2>";
foreach (\$top6 as \$f){
\$path = \$f['path'];
\$value = \$f['value'];
echo "<img src='path' width=300 alt='\$value:\$path'>";
}
echo "<div>".\$foot;

//　ヒストグラムから類似度を計算
function calcIntersection(\$target, \$files){
\$histlist = [];
foreach (\$files as \$file) {
\$hist = makeHistogram(\$file);
\$value = 0;
for (\$i = 0; \$i < count(\$target); \$i++){
\$value += min(intval(\$target&#91;\$fi&#93;), intval(\$hist&#91;\$i&#93;));
}
\$histlist&#91;&#93; = &#91;
"path" => \$file,
"value" => \$value,
];
}
usort(\$histlist, function (\$a, \$b){
return \$b['value'] - \$a['value'];
});
return \$histlist;
}```

```<?php
session_start();

// ユーザーからの入力を取得
\$input = isset(\$_GET&#91;'input'&#93; ? \$_GET&#91;'input'&#93;: "";
\$captch = "<img src='genImage.php'>";
\$msg = "5文字のひらがなを入力してください。";
\$form = <<< END_OF_FORM
<form method="GET">
<input type="text" name="input">
<input type="submit" value="OK">
</form>
END_OF_FORM;

if (isset(\$_SESSION["CAPTCH"]) && \$_SESSION["CAPTCH"] === \$input) {
\$msg = "<h3>正解です！</h3><a href='form.php'>もう一度試す</a>";
\$captch = \$form = "-";
} else {
if (\$input != ""){
\$msg = "間違い!もう一度、{\$msg}";
}
}

// HTMLを出力
echo <<< END_OF_HTML
<body>
<p>\$msg</p>
<p>\$form</p>
END_OF_HTML;```

## imageMagicを使って反転と回転を行う

```<?php
// コマンドラインから画像を取得
if (count(\$argv) <= 1){
echo "no input"; exit;
}
\$input = \$argv&#91;1&#93;;
\$outfile = preg_replace('/\.(jpeg|jpg)\$/', '-out.jpeg', \$input);
\$cmpfile = preg_replace('/\.(jpeg|jpg)\$/', '-cmp.jpeg', \$input);

\$i = new Imagick();
\$i->stripImage();
\$i->writeImage(\$cmpfile);
echo " 回転前: \$outfile\n";

// 回転用に画像を処理
\$img = new Imagick();
// 画像の向きを自動回転
img_auto_rotate(\$img);
// 画像を保存
\$img->writeImage(\$outfile);
echo " 回転後: \$outfile\n";

// 画像の向きを自動回転
function img_auto_rotate(Imagick \$img){
switch (\$img->getImageOrientation()){
case Imagick::ORIENTATION_TOPLEFT:
break;
case Imagick::ORIENTATION_TOPRIGHT:
\$img->flopImage();
break;
case Imagick::ORIENTATION_BOTTOMRIGHT:
\$img->rotateImage("#000, 180");
break;
case Imagick::ORIENTATION_LEFTTOP:
\$img->flopImage();
\$img->rotateImage("#000", -90);
break;
case Imagick::ORIENTATION_RIGHTTOP:
\$img->rotateImage("#000", 90);
break;
case Imagick::ORIENTATION_RIGHTBOTTOM:
\$img->flopImage();
\$img->rotateImage("#000", 90);
break;
case Imagick::ORIENTATION_LEFTBOTTOM:
\$img->rotateImage("#000", -90);
break;
default:
break;
}
\$img->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
return \$img;
}```

## マルコフ連鎖の実装

``` 3) array_shift(\$tmp);
set_word(\$dic, \$tmp);
if (\$w == "。 "){
\$tmp = ["@"]; continue;
}
}
return \$dic;
}

//　辞書に単語を登録
function set_word(&\$dic, \$tmp){
\$w1 = \$tmp[0];
\$w2 = \$tmp[1];
\$w3 = \$tmp[2];
if (empty(\$dic[\$w1])) \$dic[\$w1] = [];
if (empty(\$dic[\$w1][\$w2])) \$dic[\$w1][\$w2] = [];
if (empty(\$dic[\$w1][\$w2][\$w3])) \$dic[\$w1][\$w2][\$w3] = 0;
\$dic[\$w1][\$w2][\$w3]++;
}

// 辞書から作文する
function make_sentence(\$dic, \$count){
\$ret = [];
for (\$i = 0; \$i < \$count; \$i++){
\$top = \$dic["@"];
if (!\$top) break;
\$w1 = choice_word(\$top);
\$w2 = choice_word(\$top[\$w1]);
\$ret[] = \$w1;
\$ret[] = \$w2;
for (;;) {
\$w3 = choice_word(\$dic[\$w1][\$w2]);
\$ret[] = \$w3;
if (\$w3 == "。")break;
\$w1 = \$w2;
\$w2 = \$w3;
}
}
return implode("", \$ret);
}

function choice_word(\$o){
if (!is_array(\$o)) return "。 ";
\$ks = array_keys(\$o);
return \$ks[mt_rand(0, count(\$ks)-1)];
}
```

## ASCIIコード表

```<?php
//　特殊記号
\$sp = &#91;'NULL','SOH','STX','ETX','EOT','ENQ','ACK','BEL','BS','HT','LF','VT',
'FF','CR','SO','SI','DLE','DC1','DC2','DC3','DC4','NAL','SYN','ETV','CAN'm
'EM','SUB','ESC','FS','GS','RS','US','SPC'&#93;;
\$sp&#91;127&#93; = 'DEL';

\$html = "<tr><th></th>";
for(\$j = 0; \$j < 16; \$j++){
\$html .= "<th>".sprintf("%X",\$j)."</th>";
}
\$html .= "</tr>";

// characters
for (\$i = 0; \$i <= 7; \$i++){
\$html .= "<tr><th>{\$i}x</th>";
for (\$j = 0; \$j < 16; \$j++){
\$code = (\$i * 16) + \$j;
\$ch = isset(\$sp&#91;\$code&#93;) ? \$sp&#91;\$code&#93; : chr(\$code);
\$html .= "<td>\$ch</td>";
}
\$html .= "</tr>";
}

echo <<< EOS
<style>
table { margin: 12px; }
td, th {
width: 32px; text-align: center;
border-bottom: 1px solid silver;
border-right: 1px solid silver;
}
th { color: white; background-color: blue; }
</style>
<table>
\$html
</table>
EOS;```

## 月間カレンダーの描画

```<html><body>
<style>
.cal td { border-bottom: 1px solid silver; padding: 4px; }
.cur { font-size: 14px; color: black; }
.oth { font-size: 9px; color: silver; }
.sun { color: red; }
</style>
<?php
// カレンダーの描写
echo make_calendar(2018,2);

function make_calendar(\$year, \$month){
// 月初めをセット
\$t = new DateTime();
\$t->setDate(\$year, \$month, 1);
// その週の月曜日(カレンダー左上の日)を得る
\$t->modify("Mon this week");
//　月終わりをセット
\$end_t = new DateTime();
\$end_t->setDate(\$year,\$month, 1);
\$end_t->modify("Sun");
\$html = "<p>{\$year}年　{\$month}月</p>";
\$html .= "<table class='cal'>";
for (;;){
\$d = \$t->format("d");
\$w = \$t->format("w");
\$c_week = (\$w == 0) ? "sun" : ((\$w == 6) ? "sat" : "");
\$c_mon = ((int)\$t->format("m") == \$month) ? 'cur' : 'oth';
if (\$w == 1){
\$html .= "<tr>";
}
\$html .= "<td class='\$c_mon \$c_week'>\$d</td>";
if (\$w == 0){
\$html .= "</tr>";
}
\$diff = \$end_t->diff(\$t);
if (\$diff->days == 0) break;
\$t->modify("+1 days");
}
\$html .= "</table>";
return \$html;
}
?></body></html>```

## 3ヶ月後の日数

```<?php
\$t = strtotime("2018-1-1");
echo date('Y-m-d', \$t)."\n";

\$year = date('Y', \$t);
\$month = (int)date('m', \$t);
\$mm = &#91;1=>31, 2=>28, 3=>31, 4=>30, 5=>31, 6=>30,
7=>31, 8=>31, 9=>30, 10=>31, 11=>30, 12=>31];
\$isleap = (\$year%4)==0 && (\$year%100)!=0 || (\$year%400)==0;
\$mm[2] = \$isleap ? 29 :28;
// nヶ月後の日数計算
\$days = 0;
for (\$i = 0; \$i < \$n; \$i++){
\$m = \$month + \$i;
\$m = (\$m > 12) ? \$m - 12 : \$m;
\$days += \$mm[\$m];
}
\$DAY_SEC = 60 * 60 * 24;
return \$t + (\$days + \$DAY_SEC);
}```

## 再帰を使わずに中置記法

```<?php
\$str = "(1 + 2) * 3";
\$res = calc_str2(\$str);
echo \$res."\n";

function calc_str2(\$str){
\$stack = &#91;&#93;;
\$polish = &#91;&#93;;
while (\$str != ""){
\$t = get(\$str);
if (\$t == '(') {
\$stack&#91;&#93; = \$t;
continue;
}
if (\$t == ')') {
while (count(\$stack) > 0){
\$s_top = array_pop(\$stack);
if (\$s_top == '(') break;
\$polish[] = \$s_top;
}
continue;
}
while (count(\$stack) > 0){
\$s_top = \$stack[count(\$stack)-1];
if(priority(\$t) > priority(\$s_top)) break;
\$polish[] = array_pop(\$stack);
}
\$stack[] = \$t;
}

while(count(\$stack) > 0) \$polish[] = array_pop(\$stack);
echo "[".implode(" ", \$polish)."]\n";

foreach (\$polish as \$t){
if (preg_match('#^\d+\$#', \$t)){
\$tack[] = intval(\$t); continue;
}
\$b = array_pop(\$stack);
\$a = array_pop(\$stack);
switch (\$t){
case '+': \$c = \$a + \$b; break;
case '-': \$c = \$a - \$b; break;
case '*': \$c = \$a * \$b; break;
case '/': \$c = \$a / \$b; break;
default: throw new Exception("未知の文字:\$t");
}
\$stack[] = \$c;
}
return array_pop(\$stack);
}

function priority(\$c){
\$pri = ['num'=>3, '*'=>2, '/'=>2, '+'=>1, '-'=>1, '('=>0];
return isset(\$pri[\$c]) ? \$pri[\$c] : \$pri['num'];
}

function get(&\$str){
\$str = trim(\$str);
\$c = substr(\$str, 0, 1);
if (strpos("()+-*/", \$c) !== false){
\$str = substr(\$str, 1);
return \$c;
}
if (preg_match('#^(\d+)#', \$str, \$m)){
\$str = substr(\$str, strlen(\$m[1]));
return \$m[1];
}
throw new Exception("未知の文字: \$c");
}```

## 中置記法の計算方法

```<?php
\$str = "1 + 2 * 3";
\$res = calc_str(\$str);
echo \$res."\n";

function calc_str(\$str){
\$stack = &#91;&#93;;
\$polish = &#91;&#93;;
while (\$str != "") {
\$t = get(\$str);
while (count(\$stack) > 0){
\$s_top = \$stack[count(\$stack)-1];
if (priority(\$t) > priority(\$s_top))break;
\$polish[] = array_pop(\$stack);
}
\$stack[] = \$t;
}
while (count(\$stack) > 0) \$polish[] = array_pop(\$stack);
echo "[".implode(" ", \$polish)."]\n";

foreach (\$polish as \$t){
if (preg_match('#^\d+\$#', \$t)){
\$stack[] = intval(\$t); continue;
}
\$b = array_pop(\$stack);
\$a = array_pop(\$stack);
switch (\$t) {
case '+': \$c = \$a + \$b; break;
case '-': \$c = \$a - \$b; break;
case '*': \$c = \$a * \$b; break;
case '/': \$c = \$a / \$b; break;
default: throw new Exception("未知の文字:\$t");
}
\$stack[] = \$c;
}
return array_pop(\$stack);
}
function priority(\$c) {
\$pri = ['num'=>3, '*'=>2, '/'=>2, '+'=>1, '-'=>1];
return isset(\$pri[\$c]) ? \$pri[\$c] : \$pri['num'];
}

function get(&\$str) {
\$str = trim(\$str);
\$c = substr(\$str, 0, 1);
if (strpos("+-*/", \$c) !== false){
\$str = substr(\$str, 1);
return \$c;
}
if (preg_match('#^(\d+)#', \$str, \$m)){
\$str = substr (\$str, strlen(\$m[1]));
return \$m[1];
}
throw new Exception("未知の文字: \$c");
}```