マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

例の texadvent2015 の adventcal.tex の話

今年も例によって、某アドベントカレンダー某フィナーレにアレな TeX ソースが載っていますね。

[adventcal.tex]
\relax \expandafter \expandafter \expandafter \relax \catcode \lq \z
\active \let \k \catcode \chardef \x \k \lq \ \endlinechar \x \let \z
\let \k \lq \@ \k \lq \x \z \y \relax \k \x \active \let \w \jobname \z
\y \k \lq \j \tw@ \k \lq \y \@ne \z \h \chardef \h \o \count \thr@@ \y
\h \siecle \o \h \annee 15 \toks@ \yy
\z \s \string \z \n \noexpand \z \i \count@ \def \jyj \zz \y \relax \z
……(以下省略)……

うーん、例によって、チョット読み難いですね……。

とりあえずコンパイルしてみましょう。

C>pdftex adventcal
This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/W32TeX) (preloade
 format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./adventcal.tex [1{c:/texlive/2015/texmf-var/fonts/map/pdftex/updmap/pdftex.ma
……(略)……
Output written on adventcal.pdf (1 page, 44454 bytes).
Transcript written on adventcal.log.

コンパイルが通りました。出力の adventcal.pdf を開くと……。

今年(2015 年)の(アドベントな)カレンダーが出てきました。なるほど、そういうネタだったわけですね……。

アレレ、ちょっと待って。

C>dir
 ドライブ C のボリューム ラベルは OS です
 ボリューム シリアル番号は 8888-8888 です

 C:\tmp\finale のディレクトリ

2015/12/25  00:36    <DIR>          .
2015/12/25  00:36    <DIR>          ..
2015/12/25  00:36               973 adventcal.log
2015/12/25  00:36            44,454 adventcal.pdf
2015/12/25  00:13             3,398 adventcal.tex
2015/12/25  00:36             3,398 adventcal@.tex
               4 個のファイル              52,223 バイト
               2 個のディレクトリ  286,653,120,512 バイトの空き領域

何だか知らないけど、新たに .tex ファイルが作られています。しかもファイルサイズが元の adventcal.tex と全く同じ。

[adventcal.tex]
\relax \expandafter \expandafter \expandafter \relax \catcode \lq \z
\active \let \k \catcode \chardef \x \k \lq \ \endlinechar \x \let \z
\let \k \lq \@ \k \lq \x \z \y \relax \k \x \active \let \w \jobname \z
\y \k \lq \j \tw@ \k \lq \y \@ne \z \h \chardef \h \o \count \thr@@ \y
\h \siecle \o \h \annee 16 \toks@ \yy
\z \s \string \z \n \noexpand \z \i \count@ \def \jyj \zz \y \relax \z
……(以下省略)……

うむ、元の adventcal.tex と完全に一致……、あっ、一つだけ違います。5 行目の数字が、元は「15」 だったのがこちらは「16」です。

ということは、この adventcal@.texコンパイルすると……

C>pdftex adventcal@
This is pdfTeX, Version 3.14159265-2.6-1.40.16 (TeX Live 2015/W32TeX) (preloade
 format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./adventcal@.tex [1{c:/texlive/2015/texmf-var/fonts/map/pdftex/updmap/pdftex.m
……(略)……
Output written on adventcal@.pdf (1 page, 44424 bytes).
Transcript written on adventcal@.log.

来年(2016 年)の(アドベントな)カレンダーが出てきました。そして……。

C>dir
 ドライブ C のボリューム ラベルは OS です
 ボリューム シリアル番号は B888-C707 です

 C:\tmp\finale のディレクトリ

2015/12/25  00:45    <DIR>          .
2015/12/25  00:45    <DIR>          ..
2015/12/25  00:36               973 adventcal.log
2015/12/25  00:36            44,454 adventcal.pdf
2015/12/25  00:13             3,398 adventcal.tex
2015/12/25  00:45               977 adventcal@.log
2015/12/25  00:45            44,424 adventcal@.pdf
2015/12/25  00:36             3,398 adventcal@.tex
2015/12/25  00:45             3,398 adventcal@@.tex
               7 個のファイル             101,022 バイト
               2 個のディレクトリ  286,651,731,968 バイトの空き領域

また新たな adventcal@@.tex ができていますね。これをコンパイルすると……。

今度は 2017 年の(アドベントな)カレンダーが出てきました。で、また adventcal@@@.tex が作られています。以降、「TeX 文書をコンパイルすると、(アドベントな)カレンダーが組版結果となり、次の年のものの TeX 文書のソースファイルが出力される」というステップを幾らでも反復できます*1

……どこかで見てきたような展開ですね。そう、まるで山手線地球のような。

* * *

今年(2015 年)の 9 月に、(ある意味で)非情に価値の高いプログラミング技法に関する技術書が出版された。

あなたの知らない超絶技巧プログラミングの世界

あなたの知らない超絶技巧プログラミングの世界

当然の成り行きとして、TeX 界では (La)TeX で実装した Quine のネタが相次いで発表された。

私を含め「もっと質の良いQuineを見てみたい!」という人は,今後このQuineブームがTeX界にも広がり,たくさんの洗練されたQuineを鑑賞する機会に恵まれることを期待することにしましょう.

そして、誰も知っている通りクリスマスは「クワインの日」である。*2そういうわけで、今年の TeX & LaTeX アドベントカレンダーのフィナーレのネタは TeX 言語の Quine でなければならないことが、カレンダーを公開する前から決まっていたのである。

* * *

なるほど。ソースや組版結果の中では西暦年が「15」のように下 2 桁しか示されていません。ということは、きっと、コンパイルを(最初から数えて)100 回繰り返すと元に戻るのでしょう。早速やってみましょう!

……………

……………

……………

100 回目のコンパイルで出力された TeX ソースはコレです。

\relax \expandafter \expandafter \expandafter \relax \catcode \lq \z
\active \let \k \catcode \chardef \x \k \lq \ \endlinechar \x \let \z
\let \k \lq \@ \k \lq \x \z \y \relax \k \x \active \let \w \jobname \z
\y \k \lq \j \tw@ \k \lq \y \@ne \z \h \chardef \h \o \count \thr@@ \y
\h \siecle \@ne \h \annee 15 \toks@ \yy
\z \s \string \z \n \noexpand \z \i \count@ \def \jyj \zz \y \relax \z
……(以下省略)……

確かに、数字が「15」に戻ってますね。コンパイルしてみましょう。

あれっ、元のものと結果が違います。そりゃそうですね、だって、2115 年の(アドベントな)カレンダーはコレのはずですから。(手許にある 2115 年のカレンダーと見比べてください。)

それにさっきの TeX コード、よく見たら最初の adventcal.tex と一か所違ってますね。

それじゃあ Quine にならない? いや、もうチョット頑張ってみましょう。

………………………………………

………………………………………

………………………………………

C>fc adventcal.tex adventcal@@.tex
ファイル adventcal.tex と ADVENTCAL@@.TEX を比較しています
FC: 相違点は検出されませんでした

アッ、400 回目のコンパイルの後に元の adventcal.tex と完全に一致しました!!

ということは、カレンダーは 2415 年のものにはならずに 2015 年に戻ってしまったのでしょうか……? いえ、この(アドベントな)カレンダーは(2015 年のものでもありますが)間違いなく 2415 年のものになっています。何故かというと、

グレゴリオ暦の規則に従うと、
ある年のカレンダーとその 400 年後のカレンダーは
完全に一致する

からです*3。つまり、ソースコードは 400 回で巡回しますが、TeX & LaTeX アドベントカレンダーはずっとずっと続くわけです!

……うわぁ。

*1:ただしファイル名がどんどん長くなってやがてシステムのパス長の制限に引っかかってしまうので、適当なところでファイルを改名する必要がある。

*2:アレレ、今年の Quine-mas は中止なの?

*3:つまり 2015 年 X 月 Y 日と 2415 年 X 月 Y 日は同じ曜日になる。「400 年」は閏年の発生に関する規則の周期となっている。任意の連続する 400 年の期間には閏年はちょうど 97 回発生するので、そこに含まれる日数は 365 × 400 + 97 = 146097 = 7 × 20871 となり 7 で割り切れる。従って「400 年後は同じ曜日」となる。