(前回の続き)
LISP on TeX (lisp-on-tex パッケージ)
(参照:アレ)
「LISP on TeX」という怖そうな*1パッケージを使うと、LISP 的な言語でプログラミングができる。というわけで早速ナベアツしてみる……。
……と思ったら、自分の思い通りにはいかないことが解った。「3 のつく数」を判定するために、整数値を文字列に変換して文字の検索に持ち込みたいんだが、今のところ、LISP on TeX には文字列を操作する関数が十分に揃っていない。もちろん、自分で十進展開を行えば可能ではあるが、それはやりたくない。*2どうしよう……。
……仕方がないので、作ってみた。
- bxlot-string パッケージ(Gist/zr-tex8r)
これを読み込むと、LISP on TeX の大域環境に次の関数が追加される。
(\explode <文字列s>): 文字列 s を文字毎に分解したリストを作る。ただし、グループ({...}で囲まれた部分)は 1 文字と扱われる。なお、ここで「文字」というのは「文字列(string)」の構成要素のことで「TeX のトークン」に相当する。LISP on TeX に「文字型」はないので、分解後の各要素は 1 文字の文字列となる。「文字」が制御綴である場合でも、「(LISP on TeX の)トークン型」ではなく「文字列型」の値となる。 例:(explode 'a \b {\c d}')を評価すると値は('a' ' ' '\b' '{\c d}')となる。
これを利用すると、文字列の操作をリストの操作に帰着させられる。例えば、整数 n が「3 のつく数」かは、(\explode (\intTOstring \n)) の結果のリストに '3' と一致する要素があるかを調べればよい。
これで、当初の予定通りにナベアツが実装できる。
[nabeazz-lot.tex]
\documentclass{article}
\usepackage{lisp-on-tex,bxlot-string}
\usepackage{type1cm}
\newcommand*\AhoFont[1]{{\usefont{OT1}{cmfr}{m}{it}\LARGE #1}}
\newcommand*\NabeAzz[1]{\lispinterp{(\nabeazz :#1)}}
\lispinterp{%!!!!!!!!!!!!!!!!!!!!!!!!!!! LISP code
(\define \joinstr (\lambda (\sep \lst)
(\lispif (\nilQ (\cdr \lst)) (\car \lst)
(\concat (\car \lst) \sep (\joinstr \sep (\cdr \lst))))))
(\define \intlist (\lambda (\m \n)
(\lispif (\< \n \m) ()
(\cons \m (\intlist (\+ \m :1) \n)))))
(\define \memQ (\lambda (\x \lst)
(\lispif (\nilQ \lst) /f
(\lispif (\= \x (\car \lst)) /t
(\memQ \x (\cdr \lst))))))
(\define \ahoQ (\lambda (\n)
(\or (\= (\mod \n :3) :0)
(\memQ '3' (\explode (\intTOstring \n))))))
(\define \nazstr (\lambda (\n)
(\lispif (\ahoQ \n) (\concat '\AhoFont' (\group (\intTOstring \n)))
(\intTOstring \n))))
(\define \nabeazz (\lambda (\n)
(\texprint (\joinstr ' ' (\map \nazstr (\intlist :1 \n))))))
}%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\begin{document}
\NabeAzz{40}
\end{document}