(La)TeXで湯婆婆を実装してみる


# はじめに

最近はやりの湯婆婆シリーズのパロディです。(原作: [Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2))
メインの処理はTeXで書いてみたのですが，初心者ゆえ汚いかと思いますがネタですのでご容赦ください。
(よりよい方法など教えていただけると嬉しいです!)

# コード

```tex:yubaba.cls
\ProvidesClass{yubaba}[2020/11/12]

\LoadClass{jsarticle}

\usepackage{ascmac}

\def\rndchar#1{%
\newcount\cnt%
\newcount\index%
\newcount\len%
\makeatletter%
\expandafter\@tfor\expandafter\c\expandafter:\expandafter=#1\do{\advance\len by 1}%
\index=\time%
\divide\index by \len\relax%
\multiply\index by \len\relax%
\multiply\index by -1\relax%
\advance\index by \time\relax%
\advance\index by 1\relax%
\expandafter\@tfor\expandafter\c\expandafter:\expandafter=#1\do{%
\advance\cnt by 1\relax%
\ifnum\cnt=\index{\c}\fi%
}%
\makeatother%
}

\def\maketitle{%
\begin{titlepage}
\Large
\begin{quote}
  契約書だよ。そこに名前を書きな。
\end{quote}
\begin{itembox}[c]{契約書}
  \centering
  \@author
\end{itembox}
\def\newname{\rndchar{\@author}}
\begin{quote}
  フン。{\@author}というのかい。贅沢な名だねぇ。\par
  今からお前の名前は{\newname}だ。いいかい、{\newname}だよ。分かったら返事をするんだ、{\newname}!!
\end{quote}
\end{titlepage}
}
```

```LaTeX:doc.tex
\documentclass{yubaba}
\author{荻野千尋}
\begin{document}
  \maketitle
\end{document}
```

## 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211353/77ee2c14-d680-16a1-3cd9-af1bb354e1fe.png)

## 𠮷田さん

`\usepackage{otf}`したうえで`\author{{\CID{13706}}田}`とすると，𠮷田さんも契約することができます。
`\author{\CID{13706}田}`だと新しい名前が「13706」になる可能性があるので`{}`を忘れないようにしてください。
※ フォントの設定によっては「Glyph missing in font. (CID=13706, code=0x20bb7)」と怒られるので，その時は設定を変更してください。

# 解説

乱数は~~めんどくさかったので~~`\time`を使用しました。これは，0時からの経過分を示すため，異なる結果を得るには最大1分間待つ必要があります。

## カウンタの定義

```tex
\newcount\cnt%
\newcount\index%
\newcount\len%
```

必要なカウンタの定義です。

## 文字数取得

```tex
\expandafter\@tfor\expandafter\c\expandafter:\expandafter=#1\do{\advance\len by 1}%
```

引数を1文字ずつ取り出し，それぞれで`\len`に1を加えることで文字数を取得しています。`\rndchar{山田太郎}`のように直接名前を渡される場合には`\expandafter`は不要ですが，今回は`\@author`が渡されるため，これが一塊として処理されないように悲しいことになっています。

## ランダムなインデックス生成

```tex
\index=\time%
\divide\index by \len\relax%
\multiply\index by \len\relax%
\multiply\index by -1\relax%
\advance\index by \time\relax%
\advance\index by 1\relax%
```
`\time`を文字数で割って1を足した値を使用しています。
Python風にして見やすくすると

```python
# length = 4
index = time      # 例えば30
index //= length  # 7
index *= length   # 28
index *= -1       # -28
index += time     # 2
index += 1        # 3
```
といった感じです。最後に1を足しているのは，この後の処理で文字列の1文字目のインデックスを1としているためです。

ここで割り算をしているおかげで(`\divide\index by \len`)，名前が空白の時に正しくエラーになります!

```
./doc.tex:7: Arithmetic overflow.
\rndchar ... \index =\time \divide \index by \len
                                                  \multiply \index by \len \...
```

## 文字の切り出し

```tex
\expandafter\@tfor\expandafter\c\expandafter:\expandafter=#1\do{%
\advance\cnt by 1\relax%
\ifnum\cnt=\index{\c}\fi%
}%
```

文字を1文字ずつ取り出し，インデックスが先ほど計算した値と等しい時にその文字を出力しています。

# さいごに

~~残念ながら現時点のコードでは𠮷田さんが働こうとするとエラーになってしまいます。残念ながら私の力ではどうにもできませんでした……
有識者の皆様のアドバイスをお待ちしております。~~
(2020/11/13修正)𠮷田さんも働けるようになりました!!
サロゲートペア難しい……

# 参考文献

- [LaTeX2εまくろの八衢](http://xymtex.com/fujitas2/yatimata2/v200/yatimata2.pdf)
- [How do I calculate n modulo 3 in LaTeX?](https://tex.stackexchange.com/questions/34424/how-do-i-calculate-n-modulo-3-in-latex)

# 変更履歴

## 修正 (2020/11/13)

新しい名前の前後に空白が入らないようにマクロの改行をコメントアウトしました。
ついでにサンプルの名前を変更しました(山田太郎 → 荻野千尋)。

𠮷田さんの契約方法が判明しました。