diff options
Diffstat (limited to 'vhosts/blog/public/posts/2022-04-09')
| -rw-r--r-- | vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html | 216 |
1 files changed, 70 insertions, 146 deletions
diff --git a/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html index 3469e8b1..ca22ff5a 100644 --- a/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -67,22 +67,19 @@ </ol> </section> <section id="section--intro"> - <h2><a href="#section--intro">はじめに</a></h2> + <h2><a href="#section--intro">はじめに</a></h2> <p> - 本日開始された <a href="https://phperkaigi.jp/2022/" rel="noreferrer" target="_blank">PHPerKaigi 2022</a> の PHPer チャレンジにおいて、弊社 <a href="https://www.dgcircus.com/" rel="noreferrer" target="_blank">デジタルサーカス株式会社</a> の問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 + 本日開始された <a href="https://phperkaigi.jp/2022/" rel="noreferrer" target="_blank">PHPerKaigi 2022</a> の PHPer チャレンジにおいて、弊社 <a href="https://www.dgcircus.com/" rel="noreferrer" target="_blank">デジタルサーカス株式会社</a> の問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 </p> - <p> - リポジトリはこちら: <a href="https://github.com/nsfisis/PHPerKaigi2022-tokens" rel="noreferrer" target="_blank">https://github.com/nsfisis/PHPerKaigi2022-tokens</a> + リポジトリはこちら: <a href="https://github.com/nsfisis/PHPerKaigi2022-tokens" rel="noreferrer" target="_blank">https://github.com/nsfisis/PHPerKaigi2022-tokens</a> </p> </section> - <section id="section--q1-brainfuck"> - <h2><a href="#section--q1-brainfuck">第1問 brainf_ck.php</a></h2> + <h2><a href="#section--q1-brainfuck">第1問 brainf_ck.php</a></h2> <p> - ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。 + ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> <span class="line"></span> @@ -154,34 +151,28 @@ <span class="line"><span style="color:#24292E"> $👈, $📝,</span></span> <span class="line"><span style="color:#24292E">]);</span></span></code></pre> </div> - <p> - この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 + この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 </p> - <section id="section--q1-brainfuck--commentary"> - <h3><a href="#section--q1-brainfuck--commentary">解説</a></h3> + <h3><a href="#section--q1-brainfuck--commentary">解説</a></h3> <section id="section--q1-brainfuck--commentary--emoji"> - <h4><a href="#section--q1-brainfuck--commentary--emoji">絵文字</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--emoji">絵文字</a></h4> <p> - まず目につくのは大量の絵文字だろう。 PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。 + まず目につくのは大量の絵文字だろう。 PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。 </p> </section> - <section id="section--q1-brainfuck--commentary--brainfuck"> - <h4><a href="#section--q1-brainfuck--commentary--brainfuck">プログラム全体</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--brainfuck">プログラム全体</a></h4> <p> - Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。 + Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。 </p> - <p> - <a href="https://ja.wikipedia.org/wiki/Brainfuck" rel="noreferrer" target="_blank">https://ja.wikipedia.org/wiki/Brainfuck</a> + <a href="https://ja.wikipedia.org/wiki/Brainfuck" rel="noreferrer" target="_blank">https://ja.wikipedia.org/wiki/Brainfuck</a> </p> - <p> - なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。 + なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。 </p> - <div class="codeblock"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>+ + + + + + + + + +</span></span> <span class="line"><span>[</span></span> @@ -206,89 +197,71 @@ <span class="line"><span>> - .</span></span> <span class="line"><span>< .</span></span></code></pre> </div> - <p> - 実行結果はこちら: <a href="https://ideone.com/22VWmb" rel="noreferrer" target="_blank">https://ideone.com/22VWmb</a> + 実行結果はこちら: <a href="https://ideone.com/22VWmb" rel="noreferrer" target="_blank">https://ideone.com/22VWmb</a> </p> - <p> - それぞれの絵文字で表された関数が、各命令に対応している。 + それぞれの絵文字で表された関数が、各命令に対応している。 </p> - <ul> <li> <code>$👉</code>: <code>></code> </li> - <li> <code>$👈</code>: <code><</code> </li> - <li> <code>$👍</code>: <code>+</code> </li> - <li> <code>$👎</code>: <code>-</code> </li> - <li> <code>$📝</code>: <code>.</code> </li> - <li> <code>$🤡</code>: <code>[</code> </li> - <li> <code>$🎪</code>: <code>]</code> </li> </ul> - <p> <code>,</code> (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。 </p> - <p> - なお、<code>$🐘</code> はいわゆる main 関数であり、プログラムの実行部分である。 + なお、<code>$🐘</code> はいわゆる main 関数であり、プログラムの実行部分である。 </p> </section> - <section id="section--q1-brainfuck--commentary--emoji-selection"> - <h4><a href="#section--q1-brainfuck--commentary--emoji-selection">絵文字の選択</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--emoji-selection">絵文字の選択</a></h4> <p> - おおよそ意味に合致するよう選んでいるが、<code>$🤡</code> と <code>$🎪</code> は弊社デジタルサーカスにちなんでいる。 また、<code>$🐘</code> は PHP のマスコットの象に由来する。 + おおよそ意味に合致するよう選んでいるが、<code>$🤡</code> と <code>$🎪</code> は弊社デジタルサーカスにちなんでいる。 また、<code>$🐘</code> は PHP のマスコットの象に由来する。 </p> </section> - <section id="section--q1-brainfuck--commentary--strict-types"> - <h4><a href="#section--q1-brainfuck--commentary--strict-types">strict_types</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--strict-types">strict_types</a></h4> <p> <code>declare</code> 文の <code>strict_types</code> に指定できるのは、<code>0</code> か <code>1</code> の数値リテラルだが、 <code>0x0</code> や <code>0b1</code> のような値も受け付ける。 今回は、PHP 8.1 から追加された、<code>0O</code> または <code>0o</code> から始まる八進数リテラルを使った。 </p> </section> - <section id="section--q1-brainfuck--commentary--url"> - <h4><a href="#section--q1-brainfuck--commentary--url">URL</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--url">URL</a></h4> <p> - ソースコードのライセンスを示したこの部分だが、 + ソースコードのライセンスを示したこの部分だが、 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6F42C1">https</span><span style="color:#24292E">:</span><span style="color:#6A737D">//creativecommons.org/publicdomain/zero/1.0/</span></span></code></pre> </div> - <p> - 完全に合法な PHP のコードである。 <code>https:</code> 部分はラベル、<code>//</code> 以降は行コメントになっている。 + 完全に合法な PHP のコードである。 <code>https:</code> 部分はラベル、<code>//</code> 以降は行コメントになっている。 </p> </section> - <section id="section--q1-brainfuck--commentary--numbers"> - <h4><a href="#section--q1-brainfuck--commentary--numbers">リテラルなしで数値を生成する</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--numbers">リテラルなしで数値を生成する</a></h4> <p> - ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。PHP では、型変換を利用することで任意の整数を作り出すことができる。 + ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +!!</span><span style="color:#24292E">[]);</span></span> <span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">1</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +!</span><span style="color:#24292E">[]);</span></span> @@ -296,46 +269,38 @@ <span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">3</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> !</span><span style="color:#24292E">[]</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[]</span><span style="color:#D73A49">+!</span><span style="color:#24292E">[]);</span></span> <span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">10</span><span style="color:#D73A49"> ===</span><span style="color:#D73A49"> +</span><span style="color:#24292E">(</span><span style="color:#D73A49">!</span><span style="color:#24292E">[]</span><span style="color:#D73A49">.</span><span style="color:#D73A49">+!!</span><span style="color:#24292E">[]));</span></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> - <p> - また、<code>error_reporting</code> に指定しているのは <code>-1</code> である。 これは、<code>!</code> によって文字列を <code>false</code> にし、<code>+</code> によって <code>false</code> を <code>0</code> にし、さらにビット反転して <code>-1</code> にしている。 + また、<code>error_reporting</code> に指定しているのは <code>-1</code> である。 これは、<code>!</code> によって文字列を <code>false</code> にし、<code>+</code> によって <code>false</code> を <code>0</code> にし、さらにビット反転して <code>-1</code> にしている。 </p> </section> - <section id="section--q1-brainfuck--commentary--conditionals"> - <h4><a href="#section--q1-brainfuck--commentary--conditionals"><code>if</code> 文なしで条件分岐</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--conditionals"><code>if</code> 文なしで条件分岐</a></h4> <p> - 三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。 また、<code>&&</code> / <code>||</code> も使えることがある。遅延評価が不要なケースでは、<code>[$t, $f][$cond]</code> のような形で分岐することもできる。 + 三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。 また、<code>&&</code> / <code>||</code> も使えることがある。 遅延評価が不要なケースでは、<code>[$t, $f][$cond]</code> のような形で分岐することもできる。 </p> </section> - <section id="section--q1-brainfuck--commentary--loops"> - <h4><a href="#section--q1-brainfuck--commentary--loops"><code>while</code>、<code>for</code> 文なしでループ</a></h4> + <h4><a href="#section--q1-brainfuck--commentary--loops"><code>while</code>、<code>for</code> 文なしでループ</a></h4> <p> - 不動点コンビネータを使って無名再帰する (詳しい説明は省略する。これらの単語で検索してほしい)。 ここでは、一般に Z コンビネータとして知られるものを使った (<code>$z</code>)。 + 不動点コンビネータを使って無名再帰する (詳しい説明は省略する。これらの単語で検索してほしい)。 ここでは、一般に Z コンビネータとして知られるものを使った (<code>$z</code>)。 </p> - <p> - 実際のところ、<code>$🤡</code> や <code>$🎪</code>、<code>$🐘</code> は、一度 Scheme (Lisp の一種) で書いてから PHP に翻訳する形で記述した。 + 実際のところ、<code>$🤡</code> や <code>$🎪</code>、<code>$🐘</code> は、一度 Scheme (Lisp の一種) で書いてから PHP に翻訳する形で記述した。 </p> - <p> - なお、PHP は末尾再帰の最適化をおこなわない (少なくとも今のところは) ので、 あまりに長い brainf*ck プログラムを書くとスタックオーバーフローする。 + なお、PHP は末尾再帰の最適化をおこなわない (少なくとも今のところは) ので、 あまりに長い brainf*ck プログラムを書くとスタックオーバーフローする。 </p> </section> </section> </section> - <section id="section--q2-riddle"> - <h2><a href="#section--q2-riddle">第2問 riddle.php</a></h2> + <h2><a href="#section--q2-riddle">第2問 riddle.php</a></h2> <p> - ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。 + ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> <span class="line"></span> @@ -372,111 +337,87 @@ <span class="line"><span style="color:#005CC5"> echo</span><span style="color:#032F62"> "{</span><span style="color:#24292E">$x</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span> <span class="line"><span style="color:#24292E">}</span></span></code></pre> </div> - <p> - さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。トークンを得るためには、ソースコードを読み、定数 <code>N</code> を特定する必要がある。 + さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。 トークンを得るためには、ソースコードを読み、定数 <code>N</code> を特定する必要がある。 </p> - <p> - ここでは、私の想定解を解説する。 + ここでは、私の想定解を解説する。 </p> - <section id="section--q2-riddle--code-reading"> - <h3><a href="#section--q2-riddle--code-reading">読解</a></h3> + <h3><a href="#section--q2-riddle--code-reading">読解</a></h3> <p> - まずはソースコードを読んでいく。 + まずはソースコードを読んでいく。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$token </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [</span></span> -<span class="line"><span style="color:#6A737D">// 略</span></span> +<span class="line"><span style="color:#6A737D"> // 略</span></span> <span class="line"><span style="color:#24292E">];</span></span></code></pre> </div> - <p> - 数値からなる <code>$token</code> があり、各要素をループしている。 + 数値からなる <code>$token</code> があり、各要素をループしている。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $x </span><span style="color:#D73A49">^</span><span style="color:#005CC5"> N</span><span style="color:#24292E">;</span></span></code></pre> </div> - <p> - まずは排他的論理和 (xor) を取り、 + まずは排他的論理和 (xor) を取り、 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'%025b'</span><span style="color:#24292E">, $x);</span></span></code></pre> </div> - <p> - 二進数に変換して、 + 二進数に変換して、 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> str_replace</span><span style="color:#24292E">(</span><span style="color:#6F42C1">search</span><span style="color:#24292E">: [</span><span style="color:#032F62">'0'</span><span style="color:#24292E">, </span><span style="color:#032F62">'1'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">replace</span><span style="color:#24292E">: [</span><span style="color:#032F62">' '</span><span style="color:#24292E">, </span><span style="color:#032F62">'#'</span><span style="color:#24292E">], </span><span style="color:#6F42C1">subject</span><span style="color:#24292E">: $x);</span></span></code></pre> </div> - <p> - 0 を空白に、1 を <code>#</code> にし、 + 0 を空白に、1 を <code>#</code> にし、 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#24292E">$x </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> implode</span><span style="color:#24292E">(</span><span style="color:#032F62">"</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, </span><span style="color:#005CC5">str_split</span><span style="color:#24292E">($x, </span><span style="color:#6F42C1">length</span><span style="color:#24292E">: </span><span style="color:#005CC5">5</span><span style="color:#24292E">));</span></span></code></pre> </div> - <p> - 5文字ごとに区切ったあと、改行で結合している。 + 5文字ごとに区切ったあと、改行で結合している。 </p> </section> - <section id="section--q2-riddle--hint"> - <h3><a href="#section--q2-riddle--hint">ヒント</a></h3> + <h3><a href="#section--q2-riddle--hint">ヒント</a></h3> <p> - 次に、ソースコードに書いてあるヒントを読んでいく。 + 次に、ソースコードに書いてあるヒントを読んでいく。 </p> - <ul> <li> <code>N</code> それ自体は、42 や 8128 といったような特別な意味を持たず、ランダムに決められている </li> - <li> <code>$token</code> の各要素は、1文字を表す </li> - <li> 1文字は 5x5 のセルからなる </li> - <li> 出力されるのは、完全な PHPer トークンである </li> </ul> - <p> - ここで、PHPer トークンは必ず <code>#</code> 記号から始まることを思いだすと、<code>$token</code> の最初の数字 <code>0x14B499C</code> は、変換の結果 <code>#</code> になるのではないかと予想される (なお、このことは、リポジトリの README ファイルに追加ヒントとして書かれている)。 + ここで、PHPer トークンは必ず <code>#</code> 記号から始まることを思いだすと、 <code>$token</code> の最初の数字 <code>0x14B499C</code> は、変換の結果 <code>#</code> になるのではないかと予想される (なお、このことは、リポジトリの README ファイルに追加ヒントとして書かれている)。 </p> </section> - <section id="section--q2-riddle--solve"> - <h3><a href="#section--q2-riddle--solve">解く</a></h3> + <h3><a href="#section--q2-riddle--solve">解く</a></h3> <p> - ここまでわかれば、あと一歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code> に変換されるような <code>N</code> を見つければよい。 + ここまでわかれば、あと一歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code> に変換されるような <code>N</code> を見つければよい。 </p> - <p> - <code>N</code> は高々 + <code>N</code> は高々 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">assert</span><span style="color:#24292E">(</span><span style="color:#005CC5">0</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> &&</span><span style="color:#005CC5"> N</span><span style="color:#D73A49"> <=</span><span style="color:#005CC5"> 0b11111_11111_11111_11111_11111</span><span style="color:#24292E">);</span></span></code></pre> </div> - <p> - なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。 + なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> <span class="line"></span> @@ -495,11 +436,9 @@ <span class="line"><span style="color:#032F62">"#####</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#D73A49"> .</span></span> <span class="line"><span style="color:#032F62">" # # "</span><span style="color:#24292E">);</span></span></code></pre> </div> - <p> - この一連の変換に対する逆変換を考えると、次のようになる。 + この一連の変換に対する逆変換を考えると、次のようになる。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> <span class="line"></span> @@ -518,19 +457,16 @@ <span class="line"></span> <span class="line"><span style="color:#005CC5">echo</span><span style="color:#032F62"> "N = </span><span style="color:#24292E">$n</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">;</span></span></code></pre> </div> - <p> - これを実行すると、<code>N</code> が得られる。 + これを実行すると、<code>N</code> が得られる。 </p> </section> </section> - <section id="section--q3-toquine"> - <h2><a href="#section--q3-toquine">第3問 toquine.php</a></h2> + <h2><a href="#section--q3-toquine">第3問 toquine.php</a></h2> <p> - ソースコードはこちら。 + ソースコードはこちら。 </p> - <div class="codeblock" language="php"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49"><?</span><span style="color:#005CC5">php</span></span> <span class="line"></span> @@ -562,71 +498,59 @@ <span class="line"><span style="color:#24292E">$ws </span><span style="color:#D73A49">=</span><span style="color:#005CC5"> array_map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($w) => </span><span style="color:#005CC5">implode</span><span style="color:#24292E">(</span><span style="color:#032F62">', '</span><span style="color:#24292E">, $w), </span><span style="color:#005CC5">array_chunk</span><span style="color:#24292E">(</span><span style="color:#005CC5">array_map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E">($x) => </span><span style="color:#005CC5">sprintf</span><span style="color:#24292E">(</span><span style="color:#032F62">'0x'</span><span style="color:#D73A49"> .</span><span style="color:#005CC5"> chr</span><span style="color:#24292E">(</span><span style="color:#005CC5">37</span><span style="color:#24292E">) </span><span style="color:#D73A49">.</span><span style="color:#032F62"> '07X'</span><span style="color:#24292E">, $x), $xs), </span><span style="color:#005CC5">10</span><span style="color:#24292E">));</span></span> <span class="line"><span style="color:#005CC5">printf</span><span style="color:#24292E">($s, $t, </span><span style="color:#005CC5">str_rot13</span><span style="color:#24292E">(</span><span style="color:#032F62">"<<<'D'</span><span style="color:#005CC5">\n</span><span style="color:#032F62">{</span><span style="color:#24292E">$s</span><span style="color:#032F62">}</span><span style="color:#005CC5">\n</span><span style="color:#032F62">D"</span><span style="color:#24292E">), </span><span style="color:#005CC5">implode</span><span style="color:#24292E">(</span><span style="color:#032F62">",</span><span style="color:#005CC5">\n</span><span style="color:#032F62">"</span><span style="color:#24292E">, $ws));</span></span></code></pre> </div> - <p> - コメントにもあるとおり、次のようにして実行すれば答えがでてくる。 + コメントにもあるとおり、次のようにして実行すれば答えがでてくる。 </p> - <div class="codeblock" language="shell-session"> <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span>$ php toquine.php | php | php | php | ...</span></span></code></pre> </div> - <p> - 実際にはもう少しパイプで繋げなければならない。 + 実際にはもう少しパイプで繋げなければならない。 </p> - <section id="section--q3-toquine--commentary"> - <h3><a href="#section--q3-toquine--commentary">解説</a></h3> + <h3><a href="#section--q3-toquine--commentary">解説</a></h3> <section id="section--q3-toquine--commentary--quine"> - <h4><a href="#section--q3-toquine--commentary--quine">プログラム全体</a></h4> + <h4><a href="#section--q3-toquine--commentary--quine">プログラム全体</a></h4> <p> - コメントにもあるとおり、これは quine (風) のプログラムになっている。Quine とは、自分のソースコードをそっくりそのまま出力するようなプログラムのことである。 + コメントにもあるとおり、これは quine (風) のプログラムになっている。 Quine とは、自分のソースコードをそっくりそのまま出力するようなプログラムのことである。 </p> - <p> - このプログラムは、実行すると自身とほとんど同じプログラムを出力する。異なるのはトークンになっている部分のみである。 + このプログラムは、実行すると自身とほとんど同じプログラムを出力する。 異なるのはトークンになっている部分のみである。 </p> </section> - <section id="section--q3-toquine--commentary--tokens"> - <h4><a href="#section--q3-toquine--commentary--tokens">トークン</a></h4> + <h4><a href="#section--q3-toquine--commentary--tokens">トークン</a></h4> <p> <code>$xs</code> がトークンに対応している。変換のロジックは <code>riddle.php</code> とほぼ同じなので省略する。 </p> </section> - <section id="section--q3-toquine--commentary--states"> - <h4><a href="#section--q3-toquine--commentary--states">状態保持</a></h4> + <h4><a href="#section--q3-toquine--commentary--states">状態保持</a></h4> <p> - トークンの何文字目まで出力したかを、ソースコードを変えずに (quine なので) 覚えておく必要がある。このプログラムでは、トークンが出力されるとソースコードがだんだんと長くなっていくのを利用して、<code>__LINE__</code> から情報を取得している。 + トークンの何文字目まで出力したかを、ソースコードを変えずに (quine なので) 覚えておく必要がある。 このプログラムでは、トークンが出力されるとソースコードがだんだんと長くなっていくのを利用して、<code>__LINE__</code> から情報を取得している。 </p> </section> - <section id="section--q3-toquine--commentary--rot-13"> - <h4><a href="#section--q3-toquine--commentary--rot-13">ROT 13</a></h4> + <h4><a href="#section--q3-toquine--commentary--rot-13">ROT 13</a></h4> <p> - Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。これがあまり美しくないので、<code>toquine.php</code> では、ROT 13 変換を使って難読化した。 + Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。 これがあまり美しくないので、<code>toquine.php</code> では、ROT 13 変換を使って難読化した。 </p> - <p> - それにしてもなぜこんなものが標準ライブラリに……。 + それにしてもなぜこんなものが標準ライブラリに……。 </p> </section> </section> </section> - <section id="section--outro"> - <h2><a href="#section--outro">おわりに</a></h2> + <h2><a href="#section--outro">おわりに</a></h2> <p> - 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。 + 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。 </p> - <p> - 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、来年は 5問、より面白い問題を持っていきます。 + 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、 来年は 5問、より面白い問題を持っていきます。 </p> - <p> - 実はもう作りはじめているので、どうか来年もありますように……。 + 実はもう作りはじめているので、どうか来年もありますように……。 </p> </section> </div> |
