マクロツイーター

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

LaTeX 上で色々と実装してみる話(ナベアツ編-2)

前回の続き)
LISP on TeXlisp-on-tex パッケージ)
(参照:アレ

LISP on TeX」という怖そうな*1パッケージを使うと、LISP 的な言語でプログラミングができる。というわけで早速ナベアツしてみる……。

……と思ったら、自分の思い通りにはいかないことが解った。「3 のつく数」を判定するために、整数値を文字列に変換して文字の検索に持ち込みたいんだが、今のところ、LISP on TeX には文字列を操作する関数が十分に揃っていない。もちろん、自分で十進展開を行えば可能ではあるが、それはやりたくない。*2どうしよう……。

……仕方がないので、作ってみた。

これを読み込むと、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}

*1:コワクナイヨー

*2:他のプログラムのロジックと合わせたいのである。