長かったナベアツ編はようやく終わった。さて次の課題であるが、「ナベアツ」の次といえば「えるたそ」が来る、というのは TeX 芸人の間では異論のないところであろう。そこで次の命令の実装を目標とする。
\FibEltaso{<正整数a>}{<正整数b>}{<正整数n>}
: 最初の 2 項が a, b である一般フィボナッチ数列の第 n 項までの各項の整数について、その「えるたそ名」(1→「一反田えー」、2→「二反田びー」、…)を出力する。(各出力は段落で区切る。)ただし n は 2 以上とし、かつ a, b, n の値は「第 n 項までのどの項も高々十進 4 桁に収まる」範囲内で与えられるとする。
この課題は日本語の扱いのテストを兼ねている。ここでは原則として pLaTeX(+ jsarticle クラス)を用いることにする。テストでは、次の引数を与える。
\FibEltaso{8}{2}{13}
正常に動作したならば、次のような出力が得られるはずである。
なお、なんでフィボナッチなのかという疑問については右から左へ受け流すことにしよう。
TeX
なるべく奇をてらわない普通の実装、ということで。
\documentclass[a4paper]{jsarticle} \makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! BEGIN TeX code \newcount\xx@prv \newcount\xx@cur \newcount\xx@cnt \newcount\xx@res \def\xx@alpha@name#1{% \ifcase#1ぜっと\or えー\or びー\or しー\or でー\or いー\or えふ\or じー\or えいち\or あい\or じぇー\or けー\or える\or えむ\or えぬ\or おー\or ぴー\or きゅー\or あーる\or えす\or てぃー\or ゆー\or ぶい\or だぶりゅー\or えっくす\or わい\fi } \def\xx@kdigit#1{% \ifcase#1\or 一\or 二\or 三\or 四\or 五\or 六\or 七\or 八\or 九\fi } \def\xx@knumeral#1{% \expandafter\xx@knumeral@a\number#1/000\xx@nil } \def\xx@knumeral@a#1#2#3#4#5#6\xx@nil{% \xx@knumeral@b#1#2#3#4#5\xx@nil } \def\xx@knumeral@b#1/#2\xx@nil{% \xx@knumeral@c#2#1% } \def\xx@knumeral@c#1#2#3#4{% \xx@knum@pos#1{千}\xx@knum@pos#2{百}% \xx@knum@pos#3{十}\xx@kdigit{#4}% } \def\xx@knum@pos#1#2{% \ifnum#1>0 \ifnum#1>1 \xx@kdigit{#1}\fi #2\fi } \def\xx@eltaso@name#1{% \par\xx@knumeral{#1}反田% \xx@remainder{#1}{26}\xx@alpha@name{\xx@res}% } \def\xx@remainder#1#2{% \@tempcnta#1\relax \xx@res\@tempcnta \@tempcntb#2\relax \divide\@tempcnta\@tempcntb \multiply\@tempcnta-\@tempcntb \advance\xx@res\@tempcnta } \newcommand*\FibEltaso[3]{% \xx@prv=#1\relax \xx@cur=#2\relax \xx@cnt=#3\relax \xx@eltaso@name\xx@prv \xx@eltaso@name\xx@cur \advance\xx@cnt-2 \@whilenum{\xx@cnt>\z@}\do{% \xx@res\xx@prv \xx@prv\xx@cur \advance\xx@cur\xx@res \xx@eltaso@name\xx@cur \advance\xx@cnt-1 }% \par } \makeatother %!!!!!!!!!!!!!!!!!!!!!!!!! END TeX code \begin{document} \FibEltaso{8}{2}{13} \end{document}
expl3
(参照:アレ)
欲張って(ナベアツの時と同様に)完全展開可能になるように実装しようとしたら物凄く大変なことになった。今のところの感触としては、「expl3 でも完全展開可能コーディングは難行である」といえそうだ。
\documentclass[a4paper]{jsarticle} \usepackage{expl3} \ExplSyntaxOn %!!!!!!!!!!!!!!!!!!!!!!!! BEGIN expl3 code \int_new:N \l__zrxx_ct_int \cs_generate_variant:Nn \use:nn { nf } \cs_generate_variant:Nn \use:nnn { fnf } \cs_generate_variant:Nn \use:nnnn { ffff } \cs_generate_variant:Nn \prop_get:Nn { Nf } \cs_new_protected:Npn \newpar { \par } \cs_new:Nn \__zrxx_list_assign:Nn { \int_zero:N \l__zrxx_ct_int \clist_map_inline:nn {#2} { \prop_put:NVn #1 \l__zrxx_ct_int {##1} \int_incr:N \l__zrxx_ct_int } } \prop_new:N \l__zrxx_kdigit_prop \__zrxx_list_assign:Nn \l__zrxx_kdigit_prop { {}, 一 , 二 , 三 , 四 , 五 , 六 , 七 , 八 , 九 } \prop_new:N \l__zrxx_alpha_prop \__zrxx_list_assign:Nn \l__zrxx_alpha_prop { ぜっと , えー , びー , しー , でー , いー , えふ , じー , えいち , あい , じぇー , けー , える , えむ , えぬ , おー , ぴー , きゅー , あーる , えす , てぃー , ゆー , ぶい , だぶりゅー , えっくす , わい } \cs_new:Nn \zrxx_knumeral:n { \exp_args:Nf \__zrxx_knumeral_aux_i:n { \int_eval:n { \int_min:nn { 9999 } { \int_max:nn {#1} { 0 } } + 10000 } } } \cs_new:Nn \__zrxx_knumeral_aux_i:n { \__zrxx_knumeral_aux_ii:nnnnn #1 } \cs_new:Nn \__zrxx_knumeral_aux_ii:nnnnn { \use:ffff { \__zrxx_knum_pos:nn {#2} { 千 } } { \__zrxx_knum_pos:nn {#3} { 百 } } { \__zrxx_knum_pos:nn {#4} { 十 } } { \prop_get:Nn \l__zrxx_kdigit_prop {#5} } } \cs_new:Nn \__zrxx_knum_pos:nn { \int_compare:nNnT {#1} > { 0 } { \int_compare:nNnT {#1} > { 1 } { \prop_get:Nn \l__zrxx_kdigit_prop {#1} } #2 } } \cs_new:Npn \FibEltaso #1#2#3 { \use:nf { \newpar } { \__zrxx_app_xfib:nnnN {#1} {#2} {#3} \__zrxx_one_eltaso:n } } \cs_new:Nn \__zrxx_app_xfib:nnnN { \__zrxx_app_xfib_aux:ffffN {#1} {#2} { \int_eval:n { #3 - 1 } } { \__zrxx_one_eltaso:n {#1} } #4 } \cs_generate_variant:Nn \__zrxx_app_xfib:nnnN { fffN } \cs_new:Nn \__zrxx_app_xfib_aux:nnnnN { \int_compare:nNnTF {#3} > { 0 } { \__zrxx_app_xfib_aux:ffffN {#2} { \int_eval:n { #1 + #2 } } { \int_eval:n { #3 - 1 } } { \use:nf {#4} { #5 {#2} } } #5 } { #4 } } \cs_generate_variant:Nn \__zrxx_app_xfib_aux:nnnnN { ffffN } \cs_new:Nn \__zrxx_one_eltaso:n { \use:fnf { \zrxx_knumeral:n {#1} } { 反田 } { \prop_get:Nf \l__zrxx_alpha_prop { \int_mod:nn {#1} { 26 } } } \newpar } \ExplSyntaxOff %!!!!!!!!!!!!!!!!!!!!!!!! END expl3 code \begin{document} \FibEltaso{8}{2}{13} \end{document}
ここで、完全展開可能であることを確認するために文書中に
\edef\result{\FibEltaso{8}{2}{13}}\show\result
というコードを仕込んでおくと、次のような結果が端末に表示される。((\newpar
は \par
を protected なマクロで包んだもの。\par
の再定義時に \edef
で展開されないための対策。))
> \result=macro: ->\newpar 八反田えいち\newpar 二反田びー\newpar 十反田じぇー\newpar 十二反田え る\newpar 二十二反田ぶい\newpar 三十四反田えいち\newpar 五十六反田でー\newpar 九十反田える\newpar 百四十六反田ぴー\newpar 二百三十六反田びー\newpar 三百八十 二反田あーる\newpar 六百十八反田てぃー\newpar 千反田える\newpar .