<?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);
}
Month: August 2016
再帰を使わずに中置記法
<?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;
ユーザー認証
<?php
$admin_password = "m9k7PZRgG8SAySmG";
$dataFile = dirname(__FILE__).'/data/userauth.data';
$iv_a = [177,108,37,2,26,148,178,3,72,100,27,156,62,231,205,83];
$enc_iv = implode('', array_map('chr', $iv_a));
$info = "";
$m = empty($_POST['m']) ? '' : $_POST['m'];
if($m == 'add') $info = m_add();
if($m == 'get') $info = m_get();
function m_add() {
$userId = empty($_POST['userId']) ? '' $_POST['userId'];
$password = empty($_POST['password']) ? '' : $_POST['password'];
$secret = empty($_POST['secret']) ? '' : $_POST['secret'];
if ($userId == "" || $password == "" || $secret == ""){
return "ユーザー情報を正しく入力してください";
}
putUserData([
'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>
OPEN SSL
シーザー暗号の解読
シーザー暗号
<meta charset="UTF-8">
<?php
// get parameter
$str = isset($_GET["str"]) : "";
$shift = isset($_GET["shift"]) ? intval($_GET["shift"]) : 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[$c2] = $c1;
}
return $table;
}
function convert($str, $shift){
if (empty($_GET["str"])) return;
$table = makeTable($shift);
$res = "";
for ($i = 0; $i < strlen($str); $i++){
$c = substr($str, $i, 1);
$res .= isset($table[$c]) ? $table[$c] : $c;
}
$str = htmlentities($str, ENT_QUOTES);
$res = htmlentities($res, ENT_QUOTES);
echo "<div>before transfer: $str</div>";
echo "<div>after transfer: $res</div><hr>";
}
迷路の自動生成
0,";
$pat[1] = "1,";
$html = "";
for ($y = 0; $y < count($maze); $y++){ for ($x = 0; $x < count($maze); $x++){ $html .= $pat[$maze[$y][$x]]; } $html .= "\n"; } return $html; }[/php]