<?php
session_start();
// ユーザーからの入力を取得
$input = isset($_GET['input'] ? $_GET['input']: "";
// 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;
Category: other topics
imageMagicを使って反転と回転を行う
<?php
// コマンドラインから画像を取得
if (count($argv) <= 1){
echo "no input"; exit;
}
$input = $argv[1];
$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 = ['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'];
$sp[127] = '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[$code]) ? $sp[$code] : 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 = [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 = [];
$polish = [];
while ($str != ""){
$t = get($str);
if ($t == '(') {
$stack[] = $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 = [];
$polish = [];
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["inp"]) ? $_GET["inp"] : "(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('#^([0-9]+)#', $input_str, $m)){
$input_str = substr($input_str, strlen($m[1]));
return intval($m[1]);
}
}
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["rpn"]) ? $_GET["rpn"] : "1 2 3 * +";
// calculate RPN
$history = "";
$answer = calcRPN($rpn);
// calculate RPN
function calcRPN($str){
global $history;
$tokens = preg_split('#\s+#', trim($str));
$stack = [];
foreach ($tokens as $t){
if (preg_match('#\s+#', trim($str));
$stack =[];
foreach ($token as $t){
if (preg_match('#^[0-9\.]+$#', $t)){
$stack[] = 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[] = $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;