\newcount\a \newcount\b \newcount\c(2010.3.23 rudolphさんの指摘を受けて\printffizzbuzzを修正)
\newcount\n \newcount\i
\newif\ifdivisable
\def\fizzbuzz#1{%
\n=#1 \i=1
\loop \ifnum\i<\n
\printffizzbuzz
\advance \i by 1
\repeat}\def\printffizzbuzz{%\testdivisable{\i}{15} \ifdivisable fizzbuzz\par \fi\testdivisable{\i}{3} \ifdivisable fizz\par \fi\testdivisable{\i}{5} \ifdivisable buzz\par \fi\ifdivisable\else \number \i\par \fi}
\def\printffizzbuzz{%
\testdivisable{\i}{15} \ifdivisable fizzbuzz \else
\testdivisable{\i}{3} \ifdivisable fizz \else
\testdivisable{\i}{5} \ifdivisable buzz \else
\number \i \fi\fi\fi \par}
\def\testdivisable#1#2{%
\a=#1 \b=#2 \c=#1
\divide \a by \b
\multiply \a by \b
\advance \c by -\a
\ifnum\c=0 \divisabletrue \else \divisablefalse \fi}
\fizzbuzz{30}
\vfill
\eject
\end
LaTeXじゃなくて素のTeX。これを fizzbuzz.tex のような名前で保存して
tex fizzbuzz
と実行すれば dvi ができる。整数の計算には、
\newcount
コマンドでグローバルなレジスタをいくつか用意して、これを使う。これは文字通りのレジスタ計算で、レジスタに入っている値をadvance
やdivide
といったコマンドを使って書き換えながら計算を進めていく。リストやシーケンスのような気が利いたデータ構造は当然存在しないので、ループを使ってFizzBuzzするしかない。素のTeXでは、
\loop... \repeat
という構文が用意されていて、これでループが書ける。あとトリッキーなのは、
\newif
というマクロを使って\ifdivisable
という特定用途のための条件文を用意するところだろう。まあ、なんていうか、このへんはイディオムなので深く考えない。最初に見るとぎょっとするし、もっとうまい記述方法がないか考えても見るけど、結局こういうイディオムを使って書くのがいちばんしっくりくることに気がつくものだ。
printfizzbuzz のところは、こんな感じじゃないでしょうか。
返信削除\def\printffizzbuzz{%
\testdivisible{\i}{15}\ifdivisible
fizzbuzz
\else
\testdivisible{\i}{3}\ifdivisible
fizz
\else
\testdivisible{\i}{5}\ifdivisible
buzz
\else
\number\i
\fi
\fi
\fi
\par
}
インデントが反映されないようで見づらいです。すみません。
rudolphさん、ありがとうございます。どう見てもおかしかったですね……。記事のコードを修正しました。
返信削除