
前回の続き。前回の記事では“純粋な知識問題”を扱いましたが、今回は「実用的なTeX言語プログラミング」を扱います。
例の2022年の記事にある問題でプログラミングを扱っているのは6番目のFizzBuzzですが、FizzBuzzはあまり実用的とはいえないので、ここでは別の問題を扱います。
イマドキのAIのTeXプログラミングを添削する
「“HH:MM”の形式の時刻の文字列」を「0時からの経過分数」に変換する関数を実装します。TeXで“関数”を表現する方法はいくつかありますが、ここでは「値を返す先の変数を引数に渡す」という方式1にします。
「フツーのプログラミング言語から変換させると性能が良くなる2」という話を仕入れたので、ここではRubyの関数から変換させてみました。
RubyのコードではString#splitを使っていますが、TeXでsplitを作ろうとすると地獄に陥ります😱 文字列の分割をマクロ引数のパターンマッチに任せるのが“TeX言語らしいやり方”ですね🤯
※この問題ではGemini 2.5 Proを使用しました。
入力したやつ
def toMinutes(time_str) time_str.split(':').map{|x| Integer(x)}.then{|(a,b)| a*60+b} end
このRuby関数と同じことをするTeX言語マクロ\toMinutesを作ってください。インタフェースについては
value = toMinutes("12:30")
の代わりに
\toMinutes\value{12:30}
のようにします。
※パッケージは使わないでください。
出力されたやつ
% --- マクロ定義ここから --- % 計算に使用するカウンタ(整数型変数)を宣言 \newcount\hours \newcount\minutes \newcount\totalminutes % \toMinutes の内部で呼び出されるヘルパーマクロ % #1:#2\relax の形式で引数を取ることで、":"を区切り文字として % 時間と分を分割します。 % #1: 時間 (HH) % #2: 分 (MM) % #3: 結果を格納するマクロ(例: \value) \def\parseTime#1:#2\relax#3{ \hours=#1 \minutes=#2 \totalminutes=\hours \multiply\totalminutes by 60 \advance\totalminutes by \minutes % 計算結果を #3 で指定されたマクロに定義する % \edef は右辺を完全に展開してから定義する \edef#3{\the\totalminutes} } % ユーザーが呼び出すマクロ本体 % #1: 結果を格納するマクロ(例: \value) % #2: 時刻文字列(例: {12:30}) \def\toMinutes#1#2{ % \expandafter を用いて、#2の波括弧{}を取り除き、 % 中身の "HH:MM" を \parseTime マクロに渡します。 \expandafter\parseTime#2\relax#1 } % --- マクロ定義ここまで ---
添削してみるやつ
…………ほぼカンペキ(ツマラナイ😐)
インタフェースについて、自分は\valueの部分は整数レジスタを意図していたのですが、AIは“整数値マクロ”と解釈しました。もちろん(明確に指示してないので)それでも正解で、むしろ「LaTeXの命令の実装」としてはその方が適切3かもしれませんね。
マクロの引継の処理
\def\toMinutes#1#2{ % \expandafter を用いて、#2の波括弧{}を取り除き、 % 中身の "HH:MM" を \parseTime マクロに渡します。 \expandafter\parseTime#2\relax#1 }
「ユーザからもらった引数を区切り付き引数のマクロに引き継いで、パターンマッチに持ち込む」という典型的なパターンは卒なくこなせています。ただし\expandafter を用いて、#2の波括弧{}を取り除き、という説明は不適切で、実際にはここでは \expandafter は不要です。なぜなら、マクロの実引数は「マクロ呼出時の波括弧の中身」であり、従って引数#2にはそもそも波括弧は付いていないからです。
\def\toMinutes#1#2{% % #2の中身の "HH:MM" を \parseTime マクロに渡します。 \parseTime#2\relax#1% \expandafter は不要! }
「引数に含まれるマクロを展開させたい」という意図ならばこの\expandafterも意味をもちますが、時刻文字列の正当な引数は明らかに「単なる文字列」であるため、展開を考えるなら4中途半端な一回展開ではなく完全展開を施すべきです。
\def\toMinutes#1#2{% \edef\timestring{#2}% 完全展開する \expandafter\parseTime\timestring\relax#1% }
その他諸々
- ソースの行末による「余計な空白」が処理できていません。数箇所の行末に
%を補う必要がありました。
添削結果
修正後のコード:
実行例
\documentclass{article} \usepackage{ai-coding-1} \begin{document} 16:40 \toMinutes\myResult{16:40} $\to$ {\myResult} minutes \end{document}

カンペキ😍
まとめ
やっぱり、イマドキのエ~アイはマトモなのでツマラナイ😑(ざんねん🙃)
(つづく)