diff options
| author | nsfisis <nsfisis@gmail.com> | 2022-04-09 21:58:34 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2022-04-10 09:39:00 +0900 |
| commit | 1f542ef7a965b0bfc400053a254567ddf2d47df3 (patch) | |
| tree | c71bb26f9d2d4d39bc336ae4eced52f57a7fc356 | |
| parent | 1c647fbb6ff2710de6bcc8d88a874c32c0f742de (diff) | |
| download | nsfisis.github.io-1f542ef7a965b0bfc400053a254567ddf2d47df3.tar.gz nsfisis.github.io-1f542ef7a965b0bfc400053a254567ddf2d47df3.tar.zst nsfisis.github.io-1f542ef7a965b0bfc400053a254567ddf2d47df3.zip | |
new post: phperkaigi-2022-tokens
| -rw-r--r-- | content/posts/phperkaigi-2022-tokens.md | 160 | ||||
| -rw-r--r-- | docs/index.html | 12 | ||||
| -rw-r--r-- | docs/index.xml | 9 | ||||
| -rw-r--r-- | docs/posts/index.html | 12 | ||||
| -rw-r--r-- | docs/posts/index.xml | 11 | ||||
| -rw-r--r-- | docs/posts/phperkaigi-2022-tokens/index.html | 215 | ||||
| -rw-r--r-- | docs/sitemap.xml | 5 |
7 files changed, 422 insertions, 2 deletions
diff --git a/content/posts/phperkaigi-2022-tokens.md b/content/posts/phperkaigi-2022-tokens.md new file mode 100644 index 0000000..a3ff244 --- /dev/null +++ b/content/posts/phperkaigi-2022-tokens.md @@ -0,0 +1,160 @@ +--- +title: "PHPerKaigi 2022 トークン問題の解説" +date: 2022-04-09T21:50:19+09:00 +draft: false +--- + + +# はじめに + +本日開始された [PHPerKaigi 2022](https://phperkaigi.jp/2022/) の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 + +リポジトリはこちら: https://github.com/nsfisis/PHPerKaigi2022-tokens + + +注意: ネタバレ防止のため、2問目と 3問目はまだ解説を書いていない。 + + +# 第1問 brainf_ck.php + +ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。 + +```php +<?php + +declare(strict_types=0O1); + +namespace Dgcircus\PHPerKaigi\Y2022; + +/** + * @todo + * Run this program to acquire a PHPer token. + */ + +https://creativecommons.org/publicdomain/zero/1.0/ + +\error_reporting(~+!'We are hiring!'); + +$z = fn($f) => (fn($x) => $f(fn(...$xs) => $x($x)(...$xs)))(fn($x) => $f(fn(...$xs) => $x($x)(...$xs))); +$id = \spl_object_id(...); +$put = fn($c) => \printf('%c', $c); +$mm = fn($p, $n) => new \ArrayObject(\array_fill(+!![], $n, $p)); + +$👉 = fn($m, $p, $b, $e, $mp, $pc) => [++$mp, ++$pc]; +$👈 = fn($m, $p, $b, $e, $mp, $pc) => [--$mp, ++$pc]; +$👍 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, ++$m[$mp]]; +$👎 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, --$m[$mp]]; +$📝 = fn($m, $p, $b, $e, $mp, $pc) => [$mp, ++$pc, $put($m[$mp])]; +$🤡 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) { + +!![] => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) { + $b => $loop(++$pc, ++$n), + $e => $n === +!![] ? ++$pc : $loop(++$pc, --$n), + default => $loop(++$pc, $n), + })($pc, -![])], + default => [$mp, ++$pc], +}; +$🎪 = fn($m, $p, $b, $e, $mp, $pc) => match ($m[$mp]) { + +!![] => [$mp, ++$pc], + default => [$mp, $z(fn($loop) => fn($pc, $n) => match ($id($p[$pc])) { + $e => $loop(--$pc, ++$n), + $b => $n === +!![] ? $pc+![] : $loop(--$pc, --$n), + default => $loop(--$pc, $n), + })($pc, -![])], +}; +$🐘 = fn($p) => $z(fn($loop) => fn($m, $p, $b, $e, $mp, $pc) => + isset($p[$pc]) && $loop($m, $p, $b, $e, ...($p[$pc]($m, $p, $b, $e, $mp, $pc))) +)($mm(+!![], +(![].![])), $p, $id($🤡), $id($🎪), +!![], +!![]); + +$🐘([ + $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $🤡, + $👉, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $👈, $👈, $👈, $👈, $👎, + $🎪, + $👉, $👍, $👍, $👍, $👍, $👍, $📝, + $👎, $👎, $📝, + $👉, $👎, $👎, $👎, $📝, + $👉, $👎, $👎, $👎, $📝, + $👎, $👎, $📝, + $👎, $📝, + $👈, $📝, + $👉, $👉, $👎, $👎, $📝, + $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝, + $👈, $👎, $👎, $👎, $👎, $📝, + $👈, $📝, + $👉, $👍, $👍, $📝, + $👉, $👎, $📝, + $👈, $📝, +]); +``` + +この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 + + +## 解説 + +### 絵文字 + +まず目につくのは大量の絵文字だろう。 +PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。 + +### URL + +ソースコードのライセンスを示したこの部分だが、 + +```php +https://creativecommons.org/publicdomain/zero/1.0/ +``` + +完全に合法な PHP のコードである。 +`https:` 部分はラベル、`//` 以降は行コメントになっている。 + +### リテラルなしで数値を生成する + +ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 +PHP では、型変換を利用することで任意の整数を作り出すことができる。 + +```php +assert(0 === +!![]); +assert(1 === +![]); +assert(2 === ![]+![]); +assert(3 === ![]+![]+![]); +assert(10 === +(![].+!![])); +``` + +`[]` に `!` を適用すると `TRUE` が返ってくる。それに `+` +を適用すると、`bool` から `int` ヘの型変換が走り、`1` が生成される。`10` +はさらにトリッキーだ。まず `1` と `0` を作り、`.` で文字列として結合する +(`'10'`)。これに `+` を適用すると、`string` から `int` +への型変換が走り、`10` が生まれる (コード量に頓着しないなら、`1` を 10 +個足し合わせてももちろん 10 が作れる)。 + +### `if` 文なしで条件分岐 + +三項演算子ないし `match` 式を使うことで、`if` を一切書かずに条件分岐ができる。 +また、`&&` / `||` も使えることがある。 +遅延評価が不要なケースでは、`[$t, $f][$cond]` のような形で分岐することもできる。 + +### `while`、`for` 文なしでループ + +不動点コンビネータを使う (説明は省略)。ここでは、一般に Z +コンビネータとして知られるものを使った (`$z`)。 + + +### プログラム全体 + +Brainf\*ck。以上。 + + + +# 第2問 riddle.php + +前述のとおり、ネタバレ防止のため、2問目はまだ解説を書いていない。 + + +# 第3問 toquine.php + +前述のとおり、ネタバレ防止のため、3問目はまだ解説を書いていない。 diff --git a/docs/index.html b/docs/index.html index bc3627c..290ef74 100644 --- a/docs/index.html +++ b/docs/index.html @@ -81,6 +81,18 @@ <article class="first-entry"> <header class="entry-header"> + <h2>PHPerKaigi 2022 トークン問題の解説</h2> + </header> + <section class="entry-content"> + <p>はじめに 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 リポ...</p> + </section> + <footer class="entry-footer"> + <time>April 9, 2022</time> + </footer> + <a class="entry-link" href="https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> <h2>Rust のプリミティブ型はどこからやって来るか</h2> </header> <section class="entry-content"> diff --git a/docs/index.xml b/docs/index.xml index cfba333..bb1509b 100644 --- a/docs/index.xml +++ b/docs/index.xml @@ -8,6 +8,15 @@ <language>ja-JP</language> <lastBuildDate>Wed, 31 Mar 2021 01:36:49 +0900</lastBuildDate><atom:link href="https://blog.nsfisis.dev/index.xml" rel="self" type="application/rss+xml" /> <item> + <title>PHPerKaigi 2022 トークン問題の解説</title> + <link>https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/</link> + <pubDate>Sat, 09 Apr 2022 21:50:19 +0900</pubDate> + + <guid>https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/</guid> + <description>はじめに 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 リポ</description> + </item> + + <item> <title>Rust のプリミティブ型はどこからやって来るか</title> <link>https://blog.nsfisis.dev/posts/rust-where-are-primitive-types-from/</link> <pubDate>Sat, 02 Oct 2021 09:39:27 +0900</pubDate> diff --git a/docs/posts/index.html b/docs/posts/index.html index b52f380..581cc7a 100644 --- a/docs/posts/index.html +++ b/docs/posts/index.html @@ -83,6 +83,18 @@ <article class="post-entry"> <header class="entry-header"> + <h2>PHPerKaigi 2022 トークン問題の解説</h2> + </header> + <section class="entry-content"> + <p>はじめに 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 リポ...</p> + </section> + <footer class="entry-footer"> + <time>April 9, 2022</time> + </footer> + <a class="entry-link" href="https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/"></a> +</article> +<article class="post-entry"> + <header class="entry-header"> <h2>Rust のプリミティブ型はどこからやって来るか</h2> </header> <section class="entry-content"> diff --git a/docs/posts/index.xml b/docs/posts/index.xml index a83dc36..a3a07b1 100644 --- a/docs/posts/index.xml +++ b/docs/posts/index.xml @@ -6,7 +6,16 @@ <description>Recent content in Posts on REPL: Rest-Eat-Program Loop</description> <generator>Hugo -- gohugo.io</generator> <language>ja-JP</language> - <lastBuildDate>Sat, 02 Oct 2021 09:39:27 +0900</lastBuildDate><atom:link href="https://blog.nsfisis.dev/posts/index.xml" rel="self" type="application/rss+xml" /> + <lastBuildDate>Sat, 09 Apr 2022 21:50:19 +0900</lastBuildDate><atom:link href="https://blog.nsfisis.dev/posts/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title>PHPerKaigi 2022 トークン問題の解説</title> + <link>https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/</link> + <pubDate>Sat, 09 Apr 2022 21:50:19 +0900</pubDate> + + <guid>https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/</guid> + <description>はじめに 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 リポ</description> + </item> + <item> <title>Rust のプリミティブ型はどこからやって来るか</title> <link>https://blog.nsfisis.dev/posts/rust-where-are-primitive-types-from/</link> diff --git a/docs/posts/phperkaigi-2022-tokens/index.html b/docs/posts/phperkaigi-2022-tokens/index.html new file mode 100644 index 0000000..90acaf5 --- /dev/null +++ b/docs/posts/phperkaigi-2022-tokens/index.html @@ -0,0 +1,215 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + + <title>PHPerKaigi 2022 トークン問題の解説 - REPL: Rest-Eat-Program Loop</title> + + <meta name="description" content="はじめに 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 リポ"> + <meta name="author" content=""> + + <link href="https://blog.nsfisis.dev/an-old-hope.min.css" rel="stylesheet"> + <link href="https://blog.nsfisis.dev/style.css" rel="stylesheet"> + <link href="https://blog.nsfisis.dev/custom.css" rel="stylesheet"> + + <link rel="apple-touch-icon" href="https://blog.nsfisis.dev/apple-touch-icon.png"> + <link rel="icon" href="https://blog.nsfisis.dev/favicon.ico"> + <meta name="generator" content="Hugo 0.88.1" /> + + + + <script> + function setTheme() { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark'); + return; + } + + const time = new Date(); + const prev = localStorage.getItem('date'); + const date = String(time.getMonth() + 1) + '.' + String(time.getDate()); + + const now = time.getTime(); + let sunrise; + let sunset; + + function setBodyClass() { + if (now > sunrise && now < sunset) return; + document.body.classList.add('dark'); + } + + if (date !== prev) { + fetch('https://api.ipgeolocation.io/astronomy?apiKey=5ed37d85103e4defa5df4c5298ed5215') + .then((res) => res.json()) + .then((data) => { + sunrise = data.sunrise.split(':').map(Number); + sunset = data.sunset.split(':').map(Number); + }) + .catch(() => { + sunrise = [7, 0]; + sunset = [19, 0]; + }) + .finally(() => { + sunrise = time.setHours(sunrise[0], sunrise[1], 0); + sunset = time.setHours(sunset[0], sunset[1], 0); + setBodyClass(); + localStorage.setItem('sunrise', sunrise); + localStorage.setItem('sunset', sunset); + }); + localStorage.setItem('date', date); + } else { + sunrise = Number(localStorage.getItem('sunrise')); + sunset = Number(localStorage.getItem('sunset')); + setBodyClass(); + } + } + </script> + </head> + <body class="single"> + <script> + setTheme(); + </script> + <header class="header"> + <nav class="nav"> + <p class="logo"><a href="https://blog.nsfisis.dev">REPL: Rest-Eat-Program Loop</a></p> + </nav> + </header> + <main class="main"> + + +<article class="post-single"> + <header class="post-header"> + <h1 class="post-title">PHPerKaigi 2022 トークン問題の解説</h1> + <div class="post-meta">April 9, 2022</div> + </header> + <div class="post-content"><h1 id="はじめに">はじめに</h1> +<p>本日開始された <a href="https://phperkaigi.jp/2022/">PHPerKaigi 2022</a> の PHPer チャレンジにおいて、弊社デジタルサーカスの問題を 3問作成した。この記事では、これらの問題の解説をおこなう。</p> +<p>リポジトリはこちら: <a href="https://github.com/nsfisis/PHPerKaigi2022-tokens">https://github.com/nsfisis/PHPerKaigi2022-tokens</a></p> +<p>注意: ネタバレ防止のため、2問目と 3問目はまだ解説を書いていない。</p> +<h1 id="第1問-brainf_ckphp">第1問 brainf_ck.php</h1> +<p>ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672"><?</span><span style="color:#a6e22e">php</span> + +<span style="color:#66d9ef">declare</span>(<span style="color:#a6e22e">strict_types</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span><span style="color:#a6e22e">O1</span>); + +<span style="color:#66d9ef">namespace</span> <span style="color:#a6e22e">Dgcircus\PHPerKaigi\Y2022</span>; + +<span style="color:#e6db74">/** +</span><span style="color:#e6db74"> * @todo +</span><span style="color:#e6db74"> * Run this program to acquire a PHPer token. +</span><span style="color:#e6db74"> */</span> + +<span style="color:#a6e22e">https</span><span style="color:#f92672">://</span><span style="color:#a6e22e">creativecommons</span><span style="color:#f92672">.</span><span style="color:#a6e22e">org</span><span style="color:#f92672">/</span><span style="color:#a6e22e">publicdomain</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zero</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1.0</span><span style="color:#f92672">/</span> + +<span style="color:#a6e22e">\error_reporting</span>(<span style="color:#f92672">~+!</span><span style="color:#e6db74">'We are hiring!'</span>); + +$z <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($f) <span style="color:#f92672">=></span> (<span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=></span> $f(<span style="color:#a6e22e">fn</span>(<span style="color:#f92672">...</span>$xs) <span style="color:#f92672">=></span> $x($x)(<span style="color:#f92672">...</span>$xs)))(<span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=></span> $f(<span style="color:#a6e22e">fn</span>(<span style="color:#f92672">...</span>$xs) <span style="color:#f92672">=></span> $x($x)(<span style="color:#f92672">...</span>$xs))); +$id <span style="color:#f92672">=</span> <span style="color:#a6e22e">\spl_object_id</span>(<span style="color:#f92672">...</span>); +$put <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($c) <span style="color:#f92672">=></span> <span style="color:#a6e22e">\printf</span>(<span style="color:#e6db74">'%c'</span>, $c); +$mm <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($p, $n) <span style="color:#f92672">=></span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">\ArrayObject</span>(<span style="color:#a6e22e">\array_fill</span>(<span style="color:#f92672">+!!</span>[], $n, $p)); + +$👉 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> [<span style="color:#f92672">++</span>$mp, <span style="color:#f92672">++</span>$pc]; +$👈 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> [<span style="color:#f92672">--</span>$mp, <span style="color:#f92672">++</span>$pc]; +$👍 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> [$mp, <span style="color:#f92672">++</span>$pc, <span style="color:#f92672">++</span>$m[$mp]]; +$👎 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> [$mp, <span style="color:#f92672">++</span>$pc, <span style="color:#f92672">--</span>$m[$mp]]; +$📝 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> [$mp, <span style="color:#f92672">++</span>$pc, $put($m[$mp])]; +$🤡 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> <span style="color:#a6e22e">match</span> ($m[$mp]) { + <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">=></span> [$mp, $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=></span> <span style="color:#a6e22e">fn</span>($pc, $n) <span style="color:#f92672">=></span> <span style="color:#a6e22e">match</span> ($id($p[$pc])) { + $b <span style="color:#f92672">=></span> $loop(<span style="color:#f92672">++</span>$pc, <span style="color:#f92672">++</span>$n), + $e <span style="color:#f92672">=></span> $n <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">?</span> <span style="color:#f92672">++</span>$pc <span style="color:#f92672">:</span> $loop(<span style="color:#f92672">++</span>$pc, <span style="color:#f92672">--</span>$n), + <span style="color:#66d9ef">default</span> <span style="color:#f92672">=></span> $loop(<span style="color:#f92672">++</span>$pc, $n), + })($pc, <span style="color:#f92672">-!</span>[])], + <span style="color:#66d9ef">default</span> <span style="color:#f92672">=></span> [$mp, <span style="color:#f92672">++</span>$pc], +}; +$🎪 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> <span style="color:#a6e22e">match</span> ($m[$mp]) { + <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">=></span> [$mp, <span style="color:#f92672">++</span>$pc], + <span style="color:#66d9ef">default</span> <span style="color:#f92672">=></span> [$mp, $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=></span> <span style="color:#a6e22e">fn</span>($pc, $n) <span style="color:#f92672">=></span> <span style="color:#a6e22e">match</span> ($id($p[$pc])) { + $e <span style="color:#f92672">=></span> $loop(<span style="color:#f92672">--</span>$pc, <span style="color:#f92672">++</span>$n), + $b <span style="color:#f92672">=></span> $n <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">?</span> $pc<span style="color:#f92672">+!</span>[] <span style="color:#f92672">:</span> $loop(<span style="color:#f92672">--</span>$pc, <span style="color:#f92672">--</span>$n), + <span style="color:#66d9ef">default</span> <span style="color:#f92672">=></span> $loop(<span style="color:#f92672">--</span>$pc, $n), + })($pc, <span style="color:#f92672">-!</span>[])], +}; +$🐘 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($p) <span style="color:#f92672">=></span> $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=></span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=></span> + <span style="color:#a6e22e">isset</span>($p[$pc]) <span style="color:#f92672">&&</span> $loop($m, $p, $b, $e, <span style="color:#f92672">...</span>($p[$pc]($m, $p, $b, $e, $mp, $pc))) +)($mm(<span style="color:#f92672">+!!</span>[], <span style="color:#f92672">+</span>(<span style="color:#f92672">!</span>[]<span style="color:#f92672">.!</span>[])), $p, $id($🤡), $id($🎪), <span style="color:#f92672">+!!</span>[], <span style="color:#f92672">+!!</span>[]); + +$🐘([ + $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $🤡, + $👉, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, + $👈, $👈, $👈, $👈, $👎, + $🎪, + $👉, $👍, $👍, $👍, $👍, $👍, $📝, + $👎, $👎, $📝, + $👉, $👎, $👎, $👎, $📝, + $👉, $👎, $👎, $👎, $📝, + $👎, $👎, $📝, + $👎, $📝, + $👈, $📝, + $👉, $👉, $👎, $👎, $📝, + $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝, + $👈, $👎, $👎, $👎, $👎, $📝, + $👈, $📝, + $👉, $👍, $👍, $📝, + $👉, $👎, $📝, + $👈, $📝, +]); +</code></pre></div><p>この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。</p> +<h2 id="解説">解説</h2> +<h3 id="絵文字">絵文字</h3> +<p>まず目につくのは大量の絵文字だろう。 +PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。</p> +<h3 id="url">URL</h3> +<p>ソースコードのライセンスを示したこの部分だが、</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#a6e22e">https</span><span style="color:#f92672">://</span><span style="color:#a6e22e">creativecommons</span><span style="color:#f92672">.</span><span style="color:#a6e22e">org</span><span style="color:#f92672">/</span><span style="color:#a6e22e">publicdomain</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zero</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1.0</span><span style="color:#f92672">/</span> +</code></pre></div><p>完全に合法な PHP のコードである。 +<code>https:</code> 部分はラベル、<code>//</code> 以降は行コメントになっている。</p> +<h3 id="リテラルなしで数値を生成する">リテラルなしで数値を生成する</h3> +<p>ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 +PHP では、型変換を利用することで任意の整数を作り出すことができる。</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[]); +<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">1</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+!</span>[]); +<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">2</span> <span style="color:#f92672">===</span> <span style="color:#f92672">!</span>[]<span style="color:#f92672">+!</span>[]); +<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">3</span> <span style="color:#f92672">===</span> <span style="color:#f92672">!</span>[]<span style="color:#f92672">+!</span>[]<span style="color:#f92672">+!</span>[]); +<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">10</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+</span>(<span style="color:#f92672">!</span>[]<span style="color:#f92672">.+!!</span>[])); +</code></pre></div><p><code>[]</code> に <code>!</code> を適用すると <code>TRUE</code> が返ってくる。それに <code>+</code> +を適用すると、<code>bool</code> から <code>int</code> ヘの型変換が走り、<code>1</code> が生成される。<code>10</code> +はさらにトリッキーだ。まず <code>1</code> と <code>0</code> を作り、<code>.</code> で文字列として結合する +(<code>'10'</code>)。これに <code>+</code> を適用すると、<code>string</code> から <code>int</code> +への型変換が走り、<code>10</code> が生まれる (コード量に頓着しないなら、<code>1</code> を 10 +個足し合わせてももちろん 10 が作れる)。</p> +<h3 id="if-文なしで条件分岐"><code>if</code> 文なしで条件分岐</h3> +<p>三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。 +また、<code>&&</code> / <code>||</code> も使えることがある。 +遅延評価が不要なケースでは、<code>[$t, $f][$cond]</code> のような形で分岐することもできる。</p> +<h3 id="whilefor-文なしでループ"><code>while</code>、<code>for</code> 文なしでループ</h3> +<p>不動点コンビネータを使う (説明は省略)。ここでは、一般に Z +コンビネータとして知られるものを使った (<code>$z</code>)。</p> +<h3 id="プログラム全体">プログラム全体</h3> +<p>Brainf*ck。以上。</p> +<h1 id="第2問-riddlephp">第2問 riddle.php</h1> +<p>前述のとおり、ネタバレ防止のため、2問目はまだ解説を書いていない。</p> +<h1 id="第3問-toquinephp">第3問 toquine.php</h1> +<p>前述のとおり、ネタバレ防止のため、3問目はまだ解説を書いていない。</p> +</div> + +</article></main> +<footer class="footer"> + <span>© 2022 <a href="https://blog.nsfisis.dev">REPL: Rest-Eat-Program Loop</a></span> + <span>·</span> + <span>Powered by <a href="https://gohugo.io/" rel="noopener" target="_blank">Hugo️️</a>️</span> + <span>·</span> + <span>Theme️ <a href="https://github.com/nanxiaobei/hugo-paper" rel="noopener" target="_blank">Paper</a></span> +</footer> +<script src="https://blog.nsfisis.dev/highlight.min.js"></script> +<script> + hljs.initHighlightingOnLoad(); +</script> +</body> +</html> + diff --git a/docs/sitemap.xml b/docs/sitemap.xml index cbe93b4..6c86f4b 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -2,8 +2,11 @@ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> + <loc>https://blog.nsfisis.dev/posts/phperkaigi-2022-tokens/</loc> + <lastmod>2022-04-09T21:50:19+09:00</lastmod> + </url><url> <loc>https://blog.nsfisis.dev/posts/</loc> - <lastmod>2021-10-02T09:39:27+09:00</lastmod> + <lastmod>2022-04-09T21:50:19+09:00</lastmod> </url><url> <loc>https://blog.nsfisis.dev/tags/rust/</loc> <lastmod>2021-10-02T09:39:27+09:00</lastmod> |
