月間カレンダーの描画

<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;

ユーザー認証

<?php
    $admin_password = "m9k7PZRgG8SAySmG";
    $dataFile = dirname(__FILE__).'/data/userauth.data';
    $iv_a = &#91;177,108,37,2,26,148,178,3,72,100,27,156,62,231,205,83&#93;;
    $enc_iv = implode('', array_map('chr', $iv_a));

    $info = "";
    $m = empty($_POST&#91;'m'&#93;) ? '' : $_POST&#91;'m'&#93;;
    if($m == 'add') $info = m_add();
    if($m == 'get') $info = m_get();

    function m_add() {
        $userId = empty($_POST&#91;'userId'&#93;) ? '' $_POST&#91;'userId'&#93;;
        $password = empty($_POST&#91;'password'&#93;) ? '' : $_POST&#91;'password'&#93;;
        $secret = empty($_POST&#91;'secret'&#93;) ? '' : $_POST&#91;'secret'&#93;;
        if ($userId == "" || $password == "" || $secret == ""){
            return "ユーザー情報を正しく入力してください";
        }
        putUserData(&#91;
        'userId'=>$userId, 'password'=>$password,
                    'secret'=>$secret]);
        return "保存しました";
    }

   //ユーザーデータを追加 ---(*3)
    function putUserData($user){
        global $dataFile, $enc_iv, $admin_password;
        
        $salt = base64_encode(openssl_random_pseudo_bytes(16));
        $password = $user['password'];
        $user['password'] = hash('sha256', $password.$salt);
        $user['salt'] = $salt;
        $secret = openssl_encrypt(
        $user['secret'], 'aes-256-cbc',
                                  $password.$salt, 0, $enc_iv);
        $user['secret']= $secret;
        $data = getUserData();
        $data[$user['userId']] = $user;
        $json = json_encode($data);
        print_r($data, $json);
        $enc = openssl_encrypt($json, 'aes-256-cbc', $admin_password, 0, $enc_iv);
        file_put_contents($dataFile, $enc);
    }

// user transaction
    function m_get(){
        global $enc_iv;
        $userId = empty($_POST['userId']) ? '' : $_POST['userId'];
        $password = empty($_POST['password']) ? '' : $_POST['password'];
        if ($userId == "")return "input is empty";
        $data = getUserData();
        if (!isset($data[$userId])) return "情報に誤りがあります";
        $u = $data[$userId];
        $salt = $u['salt'];
        $pw_hash = hash('sha256', $password.$salt);
        if ($u['password'] != $pw_hash) return "情報にあやまりがあります";
        $secret_raw = $u['secret'];
        $secret = openssl_decrypt($secret_raw, "aes-256-cbc",
                                  $password.$salt, 0, $enc_iv);
        $secret_ = htmlentities($secret);
        return "<div class='read'><h3>ユーザー認証成功</h3>".
        "<ul><li>userId: $userId</li>".
        "<li>secret: $secret_</li></ul></div>";
    }

// get user data
    function getUserData(){
        global $dataFile, $enc_iv, $admin_password;
        $data = [];
        if (file_exists($dataFile)){
            $raw = file_get_contents($dataFile);
            $json = openssl_decrypt($raw, "aes-256-cbc",
                                    $admin_password, 0, $enc_iv);
            $data = json_decode($json, true);
        }
        return $data;
    }
?>
<html><meta charset="utf-8">
<body><style>
.read { background-color: #e0e0fc; padding: 10px; }
    form { margin-left: 10px; }
</style>
    <?php echo $info; ?>
    <h2>ユーザーの参照</h2>
    <form method="post">
    <input type="hidden" name="m" value="get">
    userId:<br><input name="userId"><br>
    password:<br><input type="password" name="password"><br>
    <input type="submit" value="参照">
</form>

<hr><h2>ユーザーの追加</h2>
<form method="post">
    <input type="hidden" name="m" value="add">
    userId:<br><input name="userId"><br>
    password:<br><input type="password" name="password"><br>
    secret(秘密のメモ):<br><input name="secret"><br>
    <input type="submit" value="add">
    </form>
</body></html>

シーザー暗号

<meta charset="UTF-8">
<?php
// get parameter
    $str = isset($_GET&#91;"str"&#93;) : "";
    $shift = isset($_GET&#91;"shift"&#93;) ? intval($_GET&#91;"shift"&#93;) : 3;
    if ($str != "")convert($str, $shift);
    $str_ = htmlentities($str, ENT_QUOTES);
// display form
echo <<< EOS
<form>
    character line: <input name="str" value="$str_"><br>
    shift: <input name="shift" value="$shift"><br>
    <input type=="submit" value="change">
</form>
    EOS;
    function makeTable($shift){
    $ch1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $shift = $shift % strlen($ch1);
        $ch2 = substr($ch1, $shift).substr($ch1, 0, $shift);
        $table = [];
        for ($i = 0; $i < strlen($ch1); $i++){
            $c1 = substr($ch1, $i, 1);
            $c2 = substr($ch2, $i, 1);
            $table&#91;$c2&#93; = $c1;
        }
        return $table;
    }
    function convert($str, $shift){
        if (empty($_GET&#91;"str"&#93;)) return;
        $table = makeTable($shift);
        $res = "";
        for ($i = 0; $i < strlen($str); $i++){
            $c = substr($str, $i, 1);
            $res .= isset($table&#91;$c&#93;) ? $table&#91;$c&#93; : $c;
        }
        $str = htmlentities($str, ENT_QUOTES);
        $res = htmlentities($res, ENT_QUOTES);
        echo "<div>before transfer: $str</div>";
        echo "<div>after transfer: $res</div><hr>";
    }