CAPTCHA

<?php
    session_start();

// ユーザーからの入力を取得
    $input = isset($_GET&#91;'input'&#93; ? $_GET&#91;'input'&#93;: "";
// CAPTCHAと入力フォームのタグを定義
    $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;

//CAPTCHAのコードが入力されたときの処理
                   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
<html><head><meta charset="UTF-8"></head>
<body>
    <h1>CAPTCHA TEST</h1>
    <p>$captcha</p>
    <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->readImage($input);
    $i->stripImage();
    $i->writeImage($cmpfile);
    echo " 回転前: $outfile\n";

    // 回転用に画像を処理
    $img = new Imagick();
    $img->readImage($input);
    // 画像の向きを自動回転
    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';

// header
    $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>
    * { margin:0; padding:0; }
    table { margin: 12px; }
    td, th {
        font-size: 12px, padding: 4px;
    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");
    $t = month_add($t, 3);
    echo date('Y-m-d', $t)."\n";

    function month_add($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");
    }

中置記法の計算方法

<?php
// check input
    $inp = isset($_GET&#91;"inp"&#93;) ? $_GET&#91;"inp"&#93; : "(1+2)*(3+4)";
// calculate
    $answer = calcInfix($inp);

// calculate
    function calcInfix($str){
        global $input_str;
        $input_str = $str;
        // main transaction
        return plus_minus();
    }
// add, minus
    function plus_minus() {
        $v = mul_div();
        while(peek() == "+" || peek() == "-"){
            $op = get();
            if ($op == "+") $v += mul_div();
            if ($op == "-") $v -= mul_div();
        }
        return $v;
    }
    function mul_div(){
        $v = paren();
        while(peek() == "*" || peek() == "/"){
            $op = get();
            if ($op == "*") $v *= paren();
            if ($op == "/") $v /= paren();
        }
        return $v;
    }

    function paren(){
        $v = get();
        if ($v == '(') {
            $v = plus_minus();
            $t = get();
            if ($t != ")") throw new Exception("カッコ未対応");
        }
        return $v;
    }

    function get(){
        global $input_str;
        $input_str = ltrim($input_str);
        $c = substr($input_str, 0, 1);
        if (strpos("+-*/()", $c) !== false){
            $input_str = substr($input_str, 1);
            return $c;
        }
        if (preg_match('#^(&#91;0-9&#93;+)#', $input_str, $m)){
            $input_str = substr($input_str, strlen($m&#91;1&#93;));
            return intval($m&#91;1&#93;);
        }
    }

    function unget($t){
        global $input_str;
        $input_str = $t . $input_str;
    }

    function peek(){
        $c = get();
        unget($c);
        return $c;
    }

    $inp_ = htmlentities($inp, ENT_QUOTES);
    echo <<< EOS
<!DOCTYPE html><meta charset="UTF-8">
<form>
    式:<input name="inp" value="inp_" size="30">
<input type="submit" value="calculate">
    </form><hr>
    <div>答え: $answer</div>
    EOS;

逆ポーランド電卓

<?php
//入力をチェック
    $rpn = isset($_GET&#91;"rpn"&#93;) ? $_GET&#91;"rpn"&#93; : "1 2 3 * +";
// calculate RPN
    $history = "";
    $answer = calcRPN($rpn);
    
    // calculate RPN
    function calcRPN($str){
        global $history;
        $tokens = preg_split('#\s+#', trim($str));
        $stack = &#91;&#93;;
        foreach ($tokens as $t){
            if (preg_match('#\s+#', trim($str));
                $stack =&#91;&#93;;
                foreach ($token as $t){
                if (preg_match('#^&#91;0-9\.&#93;+$#', $t)){
                $stack&#91;&#93; = floatval($t);
                addHistory($stack, "$t: push");
                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;
                case '%': $c = ($a % $b); break;
                default:
                return "error";
                }
                $stack&#91;&#93; = $c;
                addHistory($stack, "$t: pop $a $b, push $c");
                }
                return array_pop($stack);
        }
                function addHistory($stack, $desc){
                global $history;
                $line = "<td>$desc</td>".
                "<td>[".implode(", ", $stack)."]</td>";
                $history .= "<tr>".$line."</tr>";
                }
// input HTML form
                $rpn_ = htmltities($rpn, ENT_QUOTES);
                echo <<< EOS
<!DOCTYPE html><meta charset="UTF-8">
<form>
    RPN: <input name="rpn" value="$rpn_" size="30"><br>
    <input type="submit" value="計算">
</form><hr>
    <div>答え: $answer</div><hr>
    <table><tr><td>操作</td><td>スタック</td></tr>
$history</table>
    EOS;