summaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html')
-rw-r--r--vhosts/blog/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html94
1 files changed, 47 insertions, 47 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 c8eed57d..b4875558 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
@@ -70,7 +70,7 @@
<section id="section--intro">
<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>
@@ -81,7 +81,7 @@
<section id="section--q1-brainfuck">
<h2><a href="#section--q1-brainfuck">第1問 brainf_ck.php</a></h2>
<p>
- ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。
+ ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta">&lt;?php</span>
@@ -155,7 +155,7 @@ $🐘([
]);</code></pre>
<p>
- この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。
+ この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。
</p>
<section id="section--q1-brainfuck--commentary">
@@ -163,14 +163,14 @@ $🐘([
<section id="section--q1-brainfuck--commentary--emoji">
<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>
<p>
- Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。
+ Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。
</p>
<p>
@@ -178,7 +178,7 @@ $🐘([
</p>
<p>
- なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。
+ なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。
</p>
<pre class="highlight"><code>+ + + + + + + + + +
@@ -209,7 +209,7 @@ $🐘([
</p>
<p>
- それぞれの絵文字で表された関数が、各命令に対応している。
+ それぞれの絵文字で表された関数が、各命令に対応している。
</p>
<ul>
@@ -243,45 +243,45 @@ $🐘([
</ul>
<p>
- <code>,</code> (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。
+ <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>
<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>
<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> から始まる八進数リテラルを使った。
+ <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>
<p>
- ソースコードのライセンスを示したこの部分だが、
+ ソースコードのライセンスを示したこの部分だが、
</p>
<pre class="highlight" language="php"><code class="highlight">https:<span class="hljs-comment">//creativecommons.org/publicdomain/zero/1.0/</span></code></pre>
<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>
<p>
- ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。
+ ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。PHP では、型変換を利用することで任意の整数を作り出すことができる。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">0</span> === +!![]);
@@ -291,33 +291,33 @@ $🐘([
<span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">10</span> === +(![].+!![]));</code></pre>
<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>&apos;10&apos;</code>)。これに <code>+</code> を適用すると、<code>string</code> から <code>int</code> への型変換が走り、<code>10</code> が生まれる (コード量に頓着しないなら、<code>1</code> を 10 個足し合わせてももちろん 10 が作れる)。
+ <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>&apos;10&apos;</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>
<p>
- 三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。 また、<code>&amp;&amp;</code> / <code>||</code> も使えることがある。 遅延評価が不要なケースでは、<code>[$t, $f][$cond]</code> のような形で分岐することもできる。
+ 三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。 また、<code>&amp;&amp;</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>
<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>
@@ -326,7 +326,7 @@ $🐘([
<section id="section--q2-riddle">
<h2><a href="#section--q2-riddle">第2問 riddle.php</a></h2>
<p>
- ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。
+ ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta">&lt;?php</span>
@@ -365,17 +365,17 @@ $🐘([
}</code></pre>
<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>
<p>
- まずはソースコードを読んでいく。
+ まずはソースコードを読んでいく。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$token</span> = [
@@ -383,38 +383,38 @@ $🐘([
];</code></pre>
<p>
- 数値からなる <code>$token</code> があり、各要素をループしている。
+ 数値からなる <code>$token</code> があり、各要素をループしている。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-variable">$x</span> ^ N;</code></pre>
<p>
- まずは排他的論理和 (xor) を取り、
+ まずは排他的論理和 (xor) を取り、
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">sprintf</span>(<span class="hljs-string">&#x27;%025b&#x27;</span>, <span class="hljs-variable">$x</span>);</code></pre>
<p>
- 二進数に変換して、
+ 二進数に変換して、
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-attr">search</span>: [<span class="hljs-string">&#x27;0&#x27;</span>, <span class="hljs-string">&#x27;1&#x27;</span>], <span class="hljs-attr">replace</span>: [<span class="hljs-string">&#x27; &#x27;</span>, <span class="hljs-string">&#x27;#&#x27;</span>], <span class="hljs-attr">subject</span>: <span class="hljs-variable">$x</span>);</code></pre>
<p>
- 0 を空白に、1 を <code>#</code> にし、
+ 0 を空白に、1 を <code>#</code> にし、
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-variable">$x</span> = <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">&quot;\n&quot;</span>, <span class="hljs-title function_ invoke__">str_split</span>(<span class="hljs-variable">$x</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">5</span>));</code></pre>
<p>
- 5文字ごとに区切ったあと、改行で結合している。
+ 5文字ごとに区切ったあと、改行で結合している。
</p>
</section>
<section id="section--q2-riddle--hint">
<h3><a href="#section--q2-riddle--hint">ヒント</a></h3>
<p>
- 次に、ソースコードに書いてあるヒントを読んでいく。
+ 次に、ソースコードに書いてあるヒントを読んでいく。
</p>
<ul>
@@ -436,14 +436,14 @@ $🐘([
</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>
<p>
- ここまでわかれば、あと一歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code> に変換されるような <code>N</code> を見つければよい。
+ ここまでわかれば、あと一歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code> に変換されるような <code>N</code> を見つければよい。
</p>
<p>
@@ -453,7 +453,7 @@ $🐘([
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-title function_ invoke__">assert</span>(<span class="hljs-number">0</span> &lt;= N &amp;&amp; N &lt;= <span class="hljs-number">0b11111_11111_11111_11111_11111</span>);</code></pre>
<p>
- なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。
+ なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta">&lt;?php</span>
@@ -474,7 +474,7 @@ $🐘([
<span class="hljs-string">&quot; # # &quot;</span>);</code></pre>
<p>
- この一連の変換に対する逆変換を考えると、次のようになる。
+ この一連の変換に対する逆変換を考えると、次のようになる。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta">&lt;?php</span>
@@ -495,7 +495,7 @@ $🐘([
<span class="hljs-keyword">echo</span> <span class="hljs-string">&quot;N = <span class="hljs-subst">$n</span>\n&quot;</span>;</code></pre>
<p>
- これを実行すると、<code>N</code> が得られる。
+ これを実行すると、<code>N</code> が得られる。
</p>
</section>
</section>
@@ -503,7 +503,7 @@ $🐘([
<section id="section--q3-toquine">
<h2><a href="#section--q3-toquine">第3問 toquine.php</a></h2>
<p>
- ソースコードはこちら。
+ ソースコードはこちら。
</p>
<pre class="highlight" language="php"><code class="highlight"><span class="hljs-meta">&lt;?php</span>
@@ -537,13 +537,13 @@ $t .= implode(&quot;\n&quot;, str_split(str_replace([&#x27;</span><span class="h
<span class="hljs-title function_ invoke__">printf</span>(<span class="hljs-variable">$s</span>, <span class="hljs-variable">$t</span>, <span class="hljs-title function_ invoke__">str_rot13</span>(<span class="hljs-string">&quot;&lt;&lt;&lt;&#x27;D&#x27;\n<span class="hljs-subst">{$s}</span>\nD&quot;</span>), <span class="hljs-title function_ invoke__">implode</span>(<span class="hljs-string">&quot;,\n&quot;</span>, <span class="hljs-variable">$ws</span>));</code></pre>
<p>
- コメントにもあるとおり、次のようにして実行すれば答えがでてくる。
+ コメントにもあるとおり、次のようにして実行すれば答えがでてくる。
</p>
<pre class="highlight" language="shell-session"><code>$ php toquine.php | php | php | php | ...</code></pre>
<p>
- 実際にはもう少しパイプで繋げなければならない。
+ 実際にはもう少しパイプで繋げなければならない。
</p>
<section id="section--q3-toquine--commentary">
@@ -551,36 +551,36 @@ $t .= implode(&quot;\n&quot;, str_split(str_replace([&#x27;</span><span class="h
<section id="section--q3-toquine--commentary--quine">
<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>
<p>
- <code>$xs</code> がトークンに対応している。変換のロジックは <code>riddle.php</code> とほぼ同じなので省略する。
+ <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>
<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>
<p>
- Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。 これがあまり美しくないので、<code>toquine.php</code> では、ROT 13 変換を使って難読化した。
+ Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。これがあまり美しくないので、<code>toquine.php</code> では、ROT 13 変換を使って難読化した。
</p>
<p>
- それにしてもなぜこんなものが標準ライブラリに……。
+ それにしてもなぜこんなものが標準ライブラリに……。
</p>
</section>
</section>
@@ -589,15 +589,15 @@ $t .= implode(&quot;\n&quot;, str_split(str_replace([&#x27;</span><span class="h
<section id="section--outro">
<h2><a href="#section--outro">おわりに</a></h2>
<p>
- 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。
+ 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。
</p>
<p>
- 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、 来年は 5問、より面白い問題を持っていきます。
+ 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、来年は 5問、より面白い問題を持っていきます。
</p>
<p>
- 実はもう作りはじめているので、どうか来年もありますように……。
+ 実はもう作りはじめているので、どうか来年もありますように……。
</p>
</section>
</div>