From 88b66f82aae2d7784002b07bfc7877932da3ec94 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 19 Mar 2023 00:47:11 +0900 Subject: fix(content): fix XML notations --- .../2022-04-09/phperkaigi-2022-tokens/index.html | 328 ++++++++++----------- 1 file changed, 164 insertions(+), 164 deletions(-) (limited to 'public/posts/2022-04-09') diff --git a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html index 86679f3..d834bb8 100644 --- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -9,7 +9,7 @@ PHPerKaigi 2022 トークン問題の解説 | REPL: Rest-Eat-Program Loop - + @@ -62,69 +62,69 @@ -
-

はじめに

+
+

はじめに

- 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社 デジタルサーカス株式会社 の問題を 3問作成した。この記事では、これらの問題の解説をおこなう。 + 本日開始された PHPerKaigi 2022 の PHPer チャレンジにおいて、弊社 デジタルサーカス株式会社 の問題を 3問作成した。この記事では、これらの問題の解説をおこなう。

- リポジトリはこちら: https://github.com/nsfisis/PHPerKaigi2022-tokens + リポジトリはこちら: https://github.com/nsfisis/PHPerKaigi2022-tokens

第1問 brainf_ck.php

- ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。 + ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。

<?php
 
-  declare(strict_types=0O1);
+declare(strict_types=0O1);
 
-  namespace Dgcircus\PHPerKaigi\Y2022;
+namespace Dgcircus\PHPerKaigi\Y2022;
 
-  /**
-  * @todo
-  * Run this program to acquire a PHPer token.
-  */
+/**
+ * @todo
+ * Run this program to acquire a PHPer token.
+ */
 
-  https://creativecommons.org/publicdomain/zero/1.0/
+https://creativecommons.org/publicdomain/zero/1.0/
 
-  \error_reporting(~+!'We are hiring!');
+\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));
+$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]) {
+$👉 = 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),
+    $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]) {
+};
+$🎪 = 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),
+    $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) =>
+};
+$🐘 = 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($🎪), +!![], +!![]);
+)($mm(+!![], +(![].![])), $p, $id($🤡), $id($🎪), +!![], +!![]);
 
-  $🐘([
+$🐘([
   $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
   $🤡,
   $👉, $👍, $👍, $👍,
@@ -147,10 +147,10 @@
   $👉, $👍, $👍, $📝,
   $👉, $👎, $📝,
   $👈, $📝,
-  ]);
+]);

- この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。 + この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。

@@ -158,14 +158,14 @@

絵文字

- まず目につくのは大量の絵文字だろう。 PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。 + まず目につくのは大量の絵文字だろう。 PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。

プログラム全体

- Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。 + Brainf*ck のインタプリタとプログラムになっている。 Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。

@@ -173,16 +173,16 @@

- なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。 + なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。

+ + + + + + + + + +
 [
-> + + +
-> + + + + +
-> + + + + + + + + + + + +
-> + + + + + + + + + +
-< < < < -
+  > + + +
+  > + + + + +
+  > + + + + + + + + + + + +
+  > + + + + + + + + + +
+  < < < < -
 ]
 > + + + + + .
 - - .
@@ -200,11 +200,11 @@
 < .

- 実行結果はこちら: https://ideone.com/22VWmb + 実行結果はこちら: https://ideone.com/22VWmb

- それぞれの絵文字で表された関数が、各命令に対応している。 + それぞれの絵文字で表された関数が、各命令に対応している。

    @@ -238,45 +238,45 @@

- , (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。 + , (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。

- なお、$🐘 はいわゆる main 関数であり、プログラムの実行部分である。 + なお、$🐘 はいわゆる main 関数であり、プログラムの実行部分である。

絵文字の選択

- おおよそ意味に合致するよう選んでいるが、$🤡$🎪 は弊社デジタルサーカスにちなんでいる。 また、$🐘 は PHP のマスコットの象に由来する。 + おおよそ意味に合致するよう選んでいるが、$🤡$🎪 は弊社デジタルサーカスにちなんでいる。 また、$🐘 は PHP のマスコットの象に由来する。

strict_types

- declare 文の strict_types に指定できるのは、01 の数値リテラルだが、 0x00b1 のような値も受け付ける。 今回は、PHP 8.1 から追加された、0O または 0o から始まる八進数リテラルを使った。 + declare 文の strict_types に指定できるのは、01 の数値リテラルだが、 0x00b1 のような値も受け付ける。 今回は、PHP 8.1 から追加された、0O または 0o から始まる八進数リテラルを使った。

URL

- ソースコードのライセンスを示したこの部分だが、 + ソースコードのライセンスを示したこの部分だが、

https://creativecommons.org/publicdomain/zero/1.0/

- 完全に合法な PHP のコードである。 https: 部分はラベル、// 以降は行コメントになっている。 + 完全に合法な PHP のコードである。 https: 部分はラベル、// 以降は行コメントになっている。

リテラルなしで数値を生成する

- ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。 + ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。

assert(0 === +!![]);
@@ -286,33 +286,33 @@
 assert(10 === +(![].+!![]));

- []! を適用すると true が返ってくる。それに + を適用すると、bool から int ヘの型変換が走り、1 が生成される。10 はさらにトリッキーだ。まず 10 を作り、. で文字列として結合する ('10')。これに + を適用すると、string から int への型変換が走り、10 が生まれる (コード量に頓着しないなら、1 を 10 個足し合わせてももちろん 10 が作れる)。 + []! を適用すると true が返ってくる。それに + を適用すると、bool から int ヘの型変換が走り、1 が生成される。10 はさらにトリッキーだ。まず 10 を作り、. で文字列として結合する ('10')。これに + を適用すると、string から int への型変換が走り、10 が生まれる (コード量に頓着しないなら、1 を 10 個足し合わせてももちろん 10 が作れる)。

- また、error_reporting に指定しているのは -1 である。 これは、! によって文字列を false にし、+ によって false0 にし、さらにビット反転して -1 にしている。 + また、error_reporting に指定しているのは -1 である。 これは、! によって文字列を false にし、+ によって false0 にし、さらにビット反転して -1 にしている。

if 文なしで条件分岐

- 三項演算子ないし match 式を使うことで、if を一切書かずに条件分岐ができる。 また、&& / || も使えることがある。 遅延評価が不要なケースでは、[$t, $f][$cond] のような形で分岐することもできる。 + 三項演算子ないし match 式を使うことで、if を一切書かずに条件分岐ができる。 また、&& / || も使えることがある。 遅延評価が不要なケースでは、[$t, $f][$cond] のような形で分岐することもできる。

whilefor 文なしでループ

- 不動点コンビネータを使って無名再帰する (詳しい説明は省略する。これらの単語で検索してほしい)。 ここでは、一般に Z コンビネータとして知られるものを使った ($z)。 + 不動点コンビネータを使って無名再帰する (詳しい説明は省略する。これらの単語で検索してほしい)。 ここでは、一般に Z コンビネータとして知られるものを使った ($z)。

- 実際のところ、$🤡$🎪$🐘 は、一度 Scheme (Lisp の一種) で書いてから PHP に翻訳する形で記述した。 + 実際のところ、$🤡$🎪$🐘 は、一度 Scheme (Lisp の一種) で書いてから PHP に翻訳する形で記述した。

- なお、PHP は末尾再帰の最適化をおこなわない (少なくとも今のところは) ので、 あまりに長い brainf*ck プログラムを書くとスタックオーバーフローする。 + なお、PHP は末尾再帰の最適化をおこなわない (少なくとも今のところは) ので、 あまりに長い brainf*ck プログラムを書くとスタックオーバーフローする。

@@ -321,95 +321,95 @@

第2問 riddle.php

- ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。 + ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。

<?php
 
-  /*********************************************************
-  * This program displays a PHPer token.                  *
-  * Guess 'N'.                                            *
-  *                                                       *
-  * Hints:                                                *
-  * - N itself has no special meaning, e.g., 42, 8128,    *
-  *   it is selected at random.                           *
-  * - Each element of $token represents a single letter.  *
-  * - One letter consists of 5x5 cells.                   *
-  * - Remember, the output is a complete PHPer token.     *
-  *                                                       *
-  * License:                                              *
-  *   https://creativecommons.org/publicdomain/zero/1.0/  *
-  *********************************************************/
-  const N = 0 /* Change it to your answer. */;
-  assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
+/*********************************************************
+* This program displays a PHPer token.                  *
+* Guess 'N'.                                            *
+*                                                       *
+* Hints:                                                *
+* - N itself has no special meaning, e.g., 42, 8128,    *
+*   it is selected at random.                           *
+* - Each element of $token represents a single letter.  *
+* - One letter consists of 5x5 cells.                   *
+* - Remember, the output is a complete PHPer token.     *
+*                                                       *
+* License:                                              *
+*   https://creativecommons.org/publicdomain/zero/1.0/  *
+*********************************************************/
+const N = 0 /* Change it to your answer. */;
+assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);
 
-  $token = [
-  0x14B499C,
-  0x0BE34CC, 0x01C9C69,
-  0x0ECA069, 0x01C2449, 0x0FDB166, 0x01C9C69,
-  0x01C1C66, 0x0FC1C47, 0x01C1C66,
-  0x10C5858, 0x1E4E3B8, 0x1A2F2F8,
-  ];
-  foreach ($token as $x) {
-  $x = $x ^ N;
+$token = [
+0x14B499C,
+0x0BE34CC, 0x01C9C69,
+0x0ECA069, 0x01C2449, 0x0FDB166, 0x01C9C69,
+0x01C1C66, 0x0FC1C47, 0x01C1C66,
+0x10C5858, 0x1E4E3B8, 0x1A2F2F8,
+];
+foreach ($token as $x) {
+$x = $x ^ N;
 
-  $x = sprintf('%025b', $x);
-  $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
-  $x = implode("\n", str_split($x, length: 5));
-  echo "{$x}\n\n";
-  }
+$x = sprintf('%025b', $x); +$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x); +$x = implode("\n", str_split($x, length: 5)); +echo "{$x}\n\n"; +}

- さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。 トークンを得るためには、ソースコードを読み、定数 N を特定する必要がある。 + さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。 トークンを得るためには、ソースコードを読み、定数 N を特定する必要がある。

- ここでは、私の想定解を解説する。 + ここでは、私の想定解を解説する。

読解

- まずはソースコードを読んでいく。 + まずはソースコードを読んでいく。

$token = [
-  // 略
-  ];
+// 略 +];

- 数値からなる $token があり、各要素をループしている。 + 数値からなる $token があり、各要素をループしている。

-
  $x = $x ^ N;
+
$x = $x ^ N;

- まずは排他的論理和 (xor) を取り、 + まずは排他的論理和 (xor) を取り、

-
  $x = sprintf('%025b', $x);
+
$x = sprintf('%025b', $x);

- 二進数に変換して、 + 二進数に変換して、

-
  $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
+
$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);

- 0 を空白に、1 を # にし、 + 0 を空白に、1 を # にし、

-
  $x = implode("\n", str_split($x, length: 5));
+
$x = implode("\n", str_split($x, length: 5));

- 5文字ごとに区切ったあと、改行で結合している。 + 5文字ごとに区切ったあと、改行で結合している。

ヒント

- 次に、ソースコードに書いてあるヒントを読んでいく。 + 次に、ソースコードに書いてあるヒントを読んでいく。

    @@ -431,45 +431,45 @@

- ここで、PHPer トークンは必ず # 記号から始まることを思いだすと、 $token の最初の数字 0x14B499C は、変換の結果 # になるのではないかと予想される (なお、このことは、リポジトリの README ファイルに追加ヒントとして書かれている)。 + ここで、PHPer トークンは必ず # 記号から始まることを思いだすと、 $token の最初の数字 0x14B499C は、変換の結果 # になるのではないかと予想される (なお、このことは、リポジトリの README ファイルに追加ヒントとして書かれている)。

解く

- ここまでわかれば、あと一歩で解ける。すなわち、0x14B499C# に変換されるような N を見つければよい。 + ここまでわかれば、あと一歩で解ける。すなわち、0x14B499C# に変換されるような N を見つければよい。

- N は高々 + N は高々

assert(0 <= N && N <= 0b11111_11111_11111_11111_11111);

- なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。 + なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。

<?php
 
-  $x = 0x14B499C;
+$x = 0x14B499C;
 
-  $x = $x ^ N;
+$x = $x ^ N;
 
-  $x = sprintf('%025b', $x);
-  $x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
-  $x = implode("\n", str_split($x, length: 5));
+$x = sprintf('%025b', $x);
+$x = str_replace(search: ['0', '1'], replace: [' ', '#'], subject: $x);
+$x = implode("\n", str_split($x, length: 5));
 
-  assert($x ===
-  " # # \n" .
-  "#####\n" .
-  " # # \n" .
-  "#####\n" .
-  " # # ");
+assert($x === +" # # \n" . +"#####\n" . +" # # \n" . +"#####\n" . +" # # ");

- この一連の変換に対する逆変換を考えると、次のようになる。 + この一連の変換に対する逆変換を考えると、次のようになる。

<?php
@@ -490,7 +490,7 @@
 echo "N = $n\n";

- これを実行すると、N が得られる。 + これを実行すると、N が得られる。

@@ -498,47 +498,47 @@

第3問 toquine.php

- ソースコードはこちら。 + ソースコードはこちら。

<?php
 
-  // License: https://creativecommons.org/publicdomain/zero/1.0/
-  // This is a quine-like program to generate a PHPer token.
-  // Execute it like this: php toquine.php | php | php | php | ...
+// License: https://creativecommons.org/publicdomain/zero/1.0/
+// This is a quine-like program to generate a PHPer token.
+// Execute it like this: php toquine.php | php | php | php | ...
 
-  $s = <<<'Q'
-  <?cuc
-  // Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/
-  // Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra.
-  // Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ...
-  %f$f = %f;
-  $f = fge_ebg13($f); $kf = [
-  %f,
-  ];
-  $g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr
-  $g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], ['  ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a";
-  $jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10));
-  cevags($f, $g, fge_ebg13("<<<'Q'\a{$f}\aQ"), vzcybqr(",\a", $jf));
-  Q;
-  $s = str_rot13($s); $xs = [
-  0x0AFABEA, 0x1F294A7, 0x1F2109F, 0x1F294A7, 0x0002800, 0x1F2109F, 0x0117041, 0x1F294A7, 0x1FAD6B5, 0x1F295B7,
-  0x010FC21, 0x1FAD6B5, 0x1151151, 0x010FC21, 0x1F294A7, 0x1F295B7, 0x1FAD6B5, 0x1F294A7, 0x1F295B7, 0x1F8C63F,
-  0x1F8C631, 0x1FAD6B5, 0x17AD6BD, 0x17AD6BD, 0x1F8C63F, 0x1F295B7,
-  ];
-  $t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else
-  $t .= implode("\n", str_split(str_replace(['0','1'], ['  ','##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n";
-  $ws = array_map(fn($w) => implode(', ', $w), array_chunk(array_map(fn($x) => sprintf('0x' . chr(37) . '07X', $x), $xs), 10));
-  printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));
+$s = <<<'Q' +<?cuc +// Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/ +// Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra. +// Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ... +%f$f = %f; +$f = fge_ebg13($f); $kf = [ +%f, +]; +$g = ahyy.snyfr; sbe ($v = 0; $v <= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr +$g .= vzcybqr("\a", fge_fcyvg(fge_ercynpr(['0','1'], [' ','##'], fcevags(pue(37) . '025o', $kf[$v])), 012)) . "\a\a"; +$jf = neenl_znc(sa($j) => vzcybqr(', ', $j), neenl_puhax(neenl_znc(sa($k) => fcevags('0k' . pue(37) . '07K', $k), $kf), 10)); +cevags($f, $g, fge_ebg13("<<<'Q'\a{$f}\aQ"), vzcybqr(",\a", $jf)); +Q; +$s = str_rot13($s); $xs = [ +0x0AFABEA, 0x1F294A7, 0x1F2109F, 0x1F294A7, 0x0002800, 0x1F2109F, 0x0117041, 0x1F294A7, 0x1FAD6B5, 0x1F295B7, +0x010FC21, 0x1FAD6B5, 0x1151151, 0x010FC21, 0x1F294A7, 0x1F295B7, 0x1FAD6B5, 0x1F294A7, 0x1F295B7, 0x1F8C63F, +0x1F8C631, 0x1FAD6B5, 0x17AD6BD, 0x17AD6BD, 0x1F8C63F, 0x1F295B7, +]; +$t = null.false; for ($i = 0; $i <= intdiv(__LINE__-035,6); ++$i) if (!isset($xs[$i])) break; else +$t .= implode("\n", str_split(str_replace(['0','1'], [' ','##'], sprintf(chr(37) . '025b', $xs[$i])), 012)) . "\n\n"; +$ws = array_map(fn($w) => implode(', ', $w), array_chunk(array_map(fn($x) => sprintf('0x' . chr(37) . '07X', $x), $xs), 10)); +printf($s, $t, str_rot13("<<<'D'\n{$s}\nD"), implode(",\n", $ws));

- コメントにもあるとおり、次のようにして実行すれば答えがでてくる。 + コメントにもあるとおり、次のようにして実行すれば答えがでてくる。

$ php toquine.php | php | php | php | ...

- 実際にはもう少しパイプで繋げなければならない。 + 実際にはもう少しパイプで繋げなければならない。

@@ -546,53 +546,53 @@

プログラム全体

- コメントにもあるとおり、これは quine (風) のプログラムになっている。 Quine とは、自分のソースコードをそっくりそのまま出力するようなプログラムのことである。 + コメントにもあるとおり、これは quine (風) のプログラムになっている。 Quine とは、自分のソースコードをそっくりそのまま出力するようなプログラムのことである。

- このプログラムは、実行すると自身とほとんど同じプログラムを出力する。 異なるのはトークンになっている部分のみである。 + このプログラムは、実行すると自身とほとんど同じプログラムを出力する。 異なるのはトークンになっている部分のみである。

トークン

- $xs がトークンに対応している。変換のロジックは riddle.php とほぼ同じなので省略する。 + $xs がトークンに対応している。変換のロジックは riddle.php とほぼ同じなので省略する。

状態保持

- トークンの何文字目まで出力したかを、ソースコードを変えずに (quine なので) 覚えておく必要がある。 このプログラムでは、トークンが出力されるとソースコードがだんだんと長くなっていくのを利用して、LINE から情報を取得している。 + トークンの何文字目まで出力したかを、ソースコードを変えずに (quine なので) 覚えておく必要がある。 このプログラムでは、トークンが出力されるとソースコードがだんだんと長くなっていくのを利用して、LINE から情報を取得している。

ROT 13

- Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。 これがあまり美しくないので、toquine.php では、ROT 13 変換を使って難読化した。 + Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。 これがあまり美しくないので、toquine.php では、ROT 13 変換を使って難読化した。

- それにしてもなぜこんなものが標準ライブラリに……。 + それにしてもなぜこんなものが標準ライブラリに……。

-
-

おわりに

+
+

おわりに

- 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。 + 解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。

- 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、 来年は 5問、より面白い問題を持っていきます。 + 今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、 来年は 5問、より面白い問題を持っていきます。

- 実はもう作りはじめているので、どうか来年もありますように……。 + 実はもう作りはじめているので、どうか来年もありますように……。

-- cgit v1.2.3-70-g09d2