From 0766039bd9e6b9f5e6334e84666f5be698d41fc3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 17 Mar 2023 01:35:04 +0900 Subject: feat(nuldoc): implement syntax highlight --- .../2022-04-09/phperkaigi-2022-tokens/index.html | 258 ++++++++++----------- 1 file changed, 129 insertions(+), 129 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 9ac3f90..25873b7 100644 --- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -10,7 +10,7 @@ PHPerKaigi 2022 トークン問題の解説 | REPL: Rest-Eat-Program Loop - +
@@ -76,50 +76,50 @@ ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。

-
<?php
+            
<?php
 
-  declare(strict_types=0O1);
+  declare(strict_types=0O1);
 
-  namespace Dgcircus\PHPerKaigi\Y2022;
+  namespace Dgcircus\PHPerKaigi\Y2022;
 
-  /**
-  * @todo
+  /**
+  * @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]) {
-  +!![] => [$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) => [++$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($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($🎪), +!![], +!![]);
+  $🐘 = 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($🎪), +!![], +!![]);
 
   $🐘([
   $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
@@ -175,26 +175,26 @@
                 
                 
+ + + + + + + + + +
 [
-> + + +
-> + + + + +
-> + + + + + + + + + + + +
-> + + + + + + + + + +
-< < < < -
+> + + +
+> + + + + +
+> + + + + + + + + + + + +
+> + + + + + + + + + +
+< < < < -
 ]
-> + + + + + .
+> + + + + + .
 - - .
-> - - - .
-> - - - .
+> - - - .
+> - - - .
 - - .
 - .
-< .
-> > - - .
+< .
+> > - - .
 + + + + + + + .
-< - - - - .
-< .
-> + + .
-> - .
-< .
+< - - - - . +< . +> + + . +> - . +< .

実行結果はこちら:https://ideone.com/22VWmb @@ -277,7 +277,7 @@ ソースコードのライセンスを示したこの部分だが、

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

完全に合法な PHP のコードである。https:部分はラベル、//以降は行コメントになっている。 @@ -290,11 +290,11 @@ ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。 PHP では、型変換を利用することで任意の整数を作り出すことができる。

-
assert(0 === +!![]);
-assert(1 === +![]);
-assert(2 === ![]+![]);
-assert(3 === ![]+![]+![]);
-assert(10 === +(![].+!![]));
+
assert(0 === +!![]);
+assert(1 === +![]);
+assert(2 === ![]+![]);
+assert(3 === ![]+![]+![]);
+assert(10 === +(![].+!![]));

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

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

-
<?php
+            
<?php
 
-  /*********************************************************
+  /*********************************************************
   * This program displays a PHPer token.                  *
-  * Guess 'N'.                                            *
+  * Guess 'N'.                                            *
   *                                                       *
   * Hints:                                                *
   * - N itself has no special meaning, e.g., 42, 8128,    *
@@ -350,24 +350,24 @@ assert(10 === +(![].+!![]));
* * * 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); + *********************************************************/ + 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, + $token = [ + 0x14B499C, + 0x0BE34CC, 0x01C9C69, + 0x0ECA069, 0x01C2449, 0x0FDB166, 0x01C9C69, + 0x01C1C66, 0x0FC1C47, 0x01C1C66, + 0x10C5858, 0x1E4E3B8, 0x1A2F2F8, ]; - foreach ($token as $x) { - $x = $x ^ N; + 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"; }

@@ -384,33 +384,33 @@ assert(10 === +(![].+!![])); まずはソースコードを読んでいく。

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

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

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

まずは排他的論理和 (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 を#にし、

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

5文字ごとに区切ったあと、改行で結合している。 @@ -464,49 +464,49 @@ assert(10 === +(![].+!![]));

Nは高々

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

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

-
<?php
+              
<?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
+              
<?php
 
-$x =
-" # # \n" .
-"#####\n" .
-" # # \n" .
-"#####\n" .
-" # # ";
+$x =
+" # # \n" .
+"#####\n" .
+" # # \n" .
+"#####\n" .
+" # # ";
 
-$x = implode('', explode("\n", $x));
-$x = str_replace(search: [' ', '#'], replace: ['0', '1'], subject: $x);
-$x = bindec($x);
+$x = implode('', explode("\n", $x));
+$x = str_replace(search: [' ', '#'], replace: ['0', '1'], subject: $x);
+$x = bindec($x);
 
-$n = $x ^ 0x14B499C;
+$n = $x ^ 0x14B499C;
 
-echo "N = $n\n";
+echo "N = $n\n";

これを実行すると、Nが得られる。 @@ -520,41 +520,41 @@ echo "N = $n\n"; ソースコードはこちら。

-
<?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 = [
+  $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));
+  $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,
+  $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));
+ $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 | ...
+
$ php toquine.php | php | php | php | ...

実際にはもう少しパイプで繋げなければならない。 -- cgit v1.2.3-70-g09d2