【ちなみに🙂】
— 某ZR(ざんねん🙃) (@zr_tex8r) 2023年9月26日
TeX言語🤮のコードを英字なし🎄で書く難しさ:
・記号と数字だけで書く → わりとカンタン😍
・記号だけで書く → とてもムズカシイ😖
実は「数字を使えるか」で大きく変わってくる。#TeX #TeX言語
というわけで、本記事では「TeX言語のコード(LaTeX文書のソースも含む)を記号と数字のみを含む(チョット読みにくい🎄)コードに変換する」ための具体的な手順について解説します。
※対象とするコードはASCII文字のみを含むものに限ります。TeXエンジンの種類には依存しません。
キホン的知識
なんと、インタァーネットには「チョット読みにくいTeX言語のキホン」を解説したスバラシイ記事があります。チョット読みにくいTeX言語初心者はまずこれを読みましょう。
- TeX の難読化 ― ラング・ラグー
ここで紹介する手順では上記記事の「サーカムフレックスメソッド」(ソース上の文字を代用する^^ab
形式の文字コード表記)を利用します。
※本記事では「サーカムフレックスメソッド」のことを(例によって1)「TeXエスケープ」と呼びます。
英字をグッバイする手順
ASCII文字からなるコードを「記号と数字だけ」にするには英字(A~Z、a~z)を除去する必要があります。このため「英大文字を除去する」「英小文字を除去する」という2つのステップを順に実行することで実現します。
英大文字をグッバイする話
最初のステップとしてASCII文字のコードを「英大文字を含まないもの2」に変換します。これは機械的に処理できず個別に対処する必要がありますが、それほど難しい作業ではありません。元々、TeX言語の「プログラムっぽいコード」では大文字はほとんど使われません。TeXのプリミティブ名やキーワードは全て小文字であり、フォーマットが提供する制御綴名も大部分が小文字のみからなるからです。
このため、英大文字が出現する箇所の多くは「文字を出力する部分」になり、これについては\uppercase
を使うと対処できます。次のようなコードを考えてみましょう。
\documentclass{article} \begin{document} Hello, ZR world! \end{document}
\uppercase
を利用することで大文字を消すことができます。
\documentclass{article} \begin{document} \uppercase{h}ello, \uppercase{zr} world! \end{document}
もちろん、時には大文字を含む名前の制御綴が使われることもあり、これの対処は厄介です。
\documentclass{article} \begin{document} Hello, {\TeX} world! \end{document}
この場合は\csname~\endcsname
と\uppercase
を駆使して対処することになります。
\documentclass{article} \begin{document} \def\smalle{e} \uppercase{h}ello, \uppercase{\csname t\smalle x\endcsname} world! \end{document}
少し技巧的なので補足しておきます。\uppercase
は文字トークンだけに作用して制御綴は変化させないので、
\uppercase{\csname t\smalle x\endcsname} ↓実行 \csname T\smalle X\endcsname ↓展開(ここで \smalle も展開) \TeX
となり結果的に\TeX
が実行されます。注意すべきなのは「\uppercase
は展開可能でない」(そして\csname~\endcsname
の中は展開で処理される)ということで、このため\csname\uppercase{t}e\uppercase{x}\endcsname
とは書けません。
もう少し“機械的に処理”したいという場合は「大文字に変換する完全展開可能なマクロ(\upcase
)を作成3する」という手法が有効でしょう。
\documentclass{article} \makeatletter \def\upcase#1{\@nameuse{my@uc/#1}} \def\my@uc@a#1{\uppercase{\my@uc@b#1}} \def\my@uc@b#1#2{\@namedef{my@uc/#2}{#1}} \@tfor\my@x:=abcdefghijklmnopqrstuvwxyz\do{% \expandafter\my@uc@a\my@x\my@x} \makeatother \begin{document} \upcase{h}ello, {\csname\upcase{t}e\upcase{x}\endcsname} world! \end{document}
この\upcase
を使うことで変換がかなり楽になります。
英小文字をグッバイする話
先のステップで英大文字を除去したので残っている英字は小文字だけになります。これは「英小文字をTeXエスケープ形式に変換する」ことで機械的に除去できます。英小文字(a~z)のASCIIコードは0x61~7Aであるため、単文字(^^X
)のTeXエスケープ形式に直した場合のX
の部分の文字コードは0x21~3Aとなり、この範囲の文字は全て記号と数字になるわけです。
変換前: abcdefghijklmnopqrstuvwxyz 変換後: !"#$%&'()*+,-./0123456789:
ただしこの中の「p~y」の範囲については少し注意が必要です。例えば「w3
」という文字列の英小文字部分を上記の規則に従ってTeXエスケープに変換すると^^73
となりますが、これは16進法のTeXエスケープの形式に合致しているためs
という異なる文字列に解釈されてしまいます。
この問題を回避するため、「p~y」の範囲の文字は単文字のTeXエスケープ(^^0~^^7
)の代わりに16進法のTeXエスケープ(^^70~^^79
)に変換することにします。するとw3
の変換結果は^^773
となり、別の文字列に解釈されることはなくなります4。
まとめると、以下の手順により英小文字を除去できます。
次のような(英大文字を含まない)コードを考えてみましょう。
\catcode`\@=11 \newcount\my@n \my@n=42
先の手順に従って変換すると英小文字を含まないコードが得られます。
\^^#^^!^^74^^#^^/^^$^^%`\@=11 \^^.^^%^^77^^#^^/^^75^^.^^74\^^-^^79@^^. \^^-^^79@^^.=42
このexample-3a.texはTeXの字句解析の規則の下ではexample-3.texと全く同一のコードと解釈されるわけです。
記号と数字だけで“hello world”をやってみる話
ここまで説明した2つのステップを順に実行することで、どんなTeX言語コードでも「記号と数字だけのコード」に変換できます。例として、“hello world”のLaTeX文書を「記号と数字だけのコード」に変換してみましょう。
\documentclass{article} \begin{document} Hello, {\TeX} world! \end{document}
これは前節で例にあげたexample-2.texと同じものです。従ってここから「英大文字を除去」した結果のコード(の一例)がexample-2a.texとなります。ただし変換後のコードは横に長くなるので、改行を多めに入れておくことにします。
\documentclass{article} \begin{document} \def\smalle{e} \uppercase{h}ello, \uppercase{\csname t\smalle x\endcsname} world! \end{document}
あとはこのコードを“TeXエスケープ変換”して「英小文字を除去」すれば「数字と記号だけのコード」が完成します。
\^^$^^/^^#^^75^^-^^%^^.^^74^^#^^,^^!^^73^^73{^^!^^72^^74^^)^^#^^,^^%} \^^"^^%^^'^^)^^.{^^$^^/^^#^^75^^-^^%^^.^^74} \^^$^^%^^&\^^73^^-^^!^^,^^,^^%{^^%} \^^75^^70^^70^^%^^72^^#^^!^^73^^%{^^(}^^%^^,^^,^^/, \^^75^^70^^70^^%^^72^^#^^!^^73^^%{\^^#^^73^^.^^!^^-^^% ^^74\^^73^^-^^!^^,^^,^^% ^^78\^^%^^.^^$^^#^^73^^.^^!^^-^^%} ^^77^^/^^72^^,^^$! \^^%^^.^^${^^$^^/^^#^^75^^-^^%^^.^^74}
まるで解読不能なのでトッテモ素敵😍
実際にLaTeXで処理してみましょう。
元のコードと同じ出力が得られました😊
まとめ
というわけで、「TeX言語🤮はカンタンだからツマラナイ🙁」という人はぜひ、使う文字を制限する🎄ことに挑戦してみましょう!💁(えっ)
- 筆者が常用している用語が「TeXエスケープ」です。ちなみにこの表記に対する“正式名称”は存在しないようです。(tex.webの中では“expanded characters”のような表現が使われています。)↩
-
ただし、「A~I・P~Y」の範囲の文字はTeXエスケープで記号と数字のみの表記(
^^41
~^^49
・^^51
~^^59
)に変換できるので、実際に問題になるのは「J~O・Z」だけになります。↩ - 「完全展開可能でないもの完全展開可能にする」ための常套手段である「事前に計算してその結果を(擬似)配列に保存する」という手法を使っています。↩
-
^^
で始まる16進法のTeXエスケープの16進数値は常に丁度2桁で表されます。Unicode対応のXeTeXやLuaTeXでは0x100以上の文字コードが使われますが、その場合のTeXエスケープ表記は^^^^2603
や^^^^^^01f986
のように^
の個数を増やした形になります。↩