最近はTeX*1を触っていないのでネタがないのだが、書くと喜ぶ人がいるようなので昔twitterでつぶやいたネタの解説をする。
\let~\ifnum\let\c\newcount\let\a\advance\c\f\c\b\c\n\loop~\n<100\a\f1\a\b1\a\n1~\f=3\f0Fizz\fi~\b=5\b0Buzz\else~\f>0{\the\n}\fi\fi\ \repeat
— 紗衣 (@faogr) 2010年6月15日
FizzBuzz問題。140文字以内にするのに苦労した記憶がある。
ちゃんとTeXで書いてある*2ので、適当なファイル(fizzbuzz.texとでもしよう)に保存して、tex fizzbuzz.texすれば、*が出てきて止まるので、\endと入れるとfizzbuzz.dviを出力してくれるはずである。いちいち入れるのが面倒な場合は末尾に\endを付けて保存しておけば大丈夫。*3
適宜分けて書く。
\let~\ifnum\let\c\newcount\let\a\advance
ここは文字数を削減するため、繰り返し出てくるコントロールシーケンスを短いものに割り当てている。
~はアクティブ文字(カテゴリーコード13)なので1文字で命令となる。\aや\cもあまり考えず名前を付けているので、何らかの文書に埋め込んで使うといった用途の場合、このあたりは修正した方が良いだろう。
\c\f\c\b\c\n
カウンタ\f,\b,\nを宣言(?)。0で初期化される。それぞれ、Fizz用、Buzz用、数字用のカウンタ。
なお、これらも衝突の危険があるため注意。
\loop~\n<100 ... \repeat
カウンタ\nを99まで回すループ。
\a\f1\a\b1\a\n1
カウンタ\f,\b,\nを1加算する。
~\f=3\f0Fizz\fi
\fが3になったら\fを0にしてFizzを出力。
~\b=5\b0Buzz\else~\f>0{\the\n}\fi\fi\
\bが5になったら\bを0にしてBuzzを出力し、
\bが5でないときに、\fが0でない(FizzもBuzzも出力されていない)ときには\nの値を出力。
\
それぞれの数に対応する出力の間の区切りのスペース。これだと最後に無駄なスペースが入ってしまうので改良の余地がある。