読者です 読者をやめる 読者になる 読者になる

TeXのマクロでFizzBuzz

昨日TeXは「チューリング完全性を備えた関数型言語でもある。」というツイートを見かけました。普段レポート書く程度にしか使っていないのですが、これは面白そうだということで調べてみました。どうやらマクロを使ってできるみたいですね。メタプログラミングな感じですごく面白そうです。そして「TeXでプログラミングしました」とか変態的で面白そうだし、ブログの記事向きじゃないですかw これは書いてみるしかない。ってことでとりあえず有名どころのFizzBuzz問題をかいてみることに。以下のような感じになりました。TeX内で\FizzBuzz{範囲}と指定すれば箇条書きでFizzBuzzの結果を出力します。

%residue(剰余)の結果
\newcount \ResidueResult
%剰余を返すマクロ
\def \residue #1 #2{
	\newcount \tmp
	\newcount \tmpb
	\tmp=#1
	\tmpb=#1
	\divide \tmp by #2
	\multiply \tmp by #2
	\advance \tmpb by -\tmp
	\ResidueResult=\tmpb
}

%数字を受け取ってその数字に対応する適切な出力をする
\def \FizzBuzzUnit#1{
	\newcount \FizzFlag
	\newcount \BuzzFlag
	\newcount \AllFlag
	\FizzFlag=0
	\BuzzFlag=0
	\AllFlag=0
	\residue #1 3
	\ifnum \ResidueResult=0
		\FizzFlag=1
	\fi
	\residue #1 5
	\ifnum \ResidueResult=0
		\BuzzFlag=1
	\fi
	\advance \AllFlag by \FizzFlag
	\advance \AllFlag by \BuzzFlag
	\ifnum \FizzFlag=1
		Fizz
	\fi
	\ifnum \BuzzFlag=1
		Buzz
	\fi
	\ifnum \AllFlag=0
		#1
	\fi
	}

%FizzBuzzの出力の整形
\def \FizzBuzz #1{
\begin{itemize}
	\newcount \cnt
	\newcount \maxIndex
	\cnt=1
	\maxIndex #1
	\advance \maxIndex by 1 
	\loop \ifnum \maxIndex>\cnt
		\item \FizzBuzzUnit{\the\cnt}
		\advance \cnt by 1
	\repeat
\end{itemize}
}

まず面倒だと思ったのが四則演算ですね。演算子でa+bじゃなくて\advanceとか使わないといけないので非常に面倒。ってかこれはありえない。マクロなんで返り値をもてるはずも\residueみれば分かるようにグローバル変数に代入して間接的に結果を返しています。これはちょっとトリッキーってかプログラムの規模が多くなるにつれ命名規則をしっかり決めとかないと衝突しますね。
 そして許せないことはないですが、if文,loopの構文もなんか奇妙です。変数名とかも制限きついですね。さらにマクロの途中で空いた行入れるとコンパイルエラーを吐くのでそれも無理みたいです。これはコメントという形で回避可能ですが。
 ただ、TeXの文章を整形するマクロとしては十分すぎるほど強力な気がします。整形自体はTeXがやってくれちゃうのでWordのマクロなんかよりも強力かも(Word全然使わないので知らないのですが)しれません。がんばれば入力した数式を展開するなんて高度なこともで きちゃうんじゃないですかね?
TeXでプログラミングすごく面白いのでこれはハマりそうです。