今日は旦那さんと話していて面白い展開になった。元々はものを作ることと作ったものを見てもらうことについて考えていて、プログラマである旦那さんに質問したのだ。自分が作ったプログラムを見て見て!って思う時、そのプログラムを書くのは楽しかったですか?と。そうしたら、旦那さんがこう答えた。
「電卓を自分で作った時は、これはすごいものを作ってしまったぞ!って思ったな」
「電卓?」
最初はいまいちピンとこなかった。
「電卓アプリとかじゃなくて、ターミナルに数式を打ち込んで、それで答えが出るやつね」
「ああ、なるほど。じゃあ構文解析とか文字列操作とか、結構難しいですね」
「構文解析って言っても簡単なのだけどね。どんな数式を入れても壊れないヤツが作れて、ちょっとこれはすごいぞ、と。もちろん壊れた式を入れたら壊れた結果が出てくるんだけど、プログラム自体は壊れない」
「確かにそれはすごいですね。ちょっと待ってください、どんな数式を入れたら壊れそうかなぁ、って今想像してみるんで」
そう言って私はしばらく考え込んだ。まず順当に見て0の扱いに困るはずだ。00とかいう文字列が入ったら壊れてしまうんじゃなかろうか、これ、と考えながら、そもそも電卓を実装するにはどうしたらいいのか考えていた。四則演算をするのなら、逆ポーランド記法を使うんだったか、とうろ覚えの知識を思い出しながら、自分で考えた実装方法を口に出した。
「まず、入力された式を正規表現で数字と符号にする必要があって、次にそれをスタックに積んで、そっから計算、ですよね」
「いきなり高度なのきた」
「確かに軽くスタックに積んでとか言いましたけど、そこ難しいですよね」
「いや違う、僕がやったのはもっと低レベルな方法」
「どういうことですか?」
「いや、四則演算だと掛け算が強いじゃないですか。だからまずそこを探す」
「はい」
そこは簡単に理解できた。旦那さんが続ける。
「で、例えば10*10があったとして、その答えは100で3桁に収まる。A*Bがあったらその答えの桁数はAの桁数+Bの桁数以下になることに注目する」
「ん?目の付け所がシャープすぎて、何を狙ってるのかわからないんですが…」
「つまり、掛け算を見つけたら、その両側を一文字ずつ、掛け算の前は前に向かって、後ろは後ろに向かって、他の符号が現れるか文字列が終わるかするまで読み込む。数字の桁数がわかんないからね」
「そういえば、Cですよね?」
「いや、Pascal」
「なるほど」
「で、得た数字で掛け算して、その場所の掛け算を答えの数字で書き換える」
「なるほど!だから桁数が重要だったと」
「そうそう。割り算も同じ要領で、あとは同じことを繰り返して足し算引き算だけにして、普通に計算するだけ」
「その発想はなかったですわー」
そう、確かにその発想はなかったのだけれど、それでも壊れないように作るには細かいところに気を配ってやらなきゃならないので(だってPascalでString使うときはポインタだし)、やっぱりその電卓プログラムはすごいと思う。
「これが僕が中学生の頃でね、まだギリギリインターネットがない頃だったからプログラムのコピペとかもなくて、雑誌に載ってたこの方法を自分で実装してみるしかなくて、できた時は結構すごいと思ったね。もちろんこれだとカッコには対応してなくて、それができたのはもっと全然あとなんだけど」
そう言っている旦那さんの顔は本当に眩しくて、心からプログラミングが好きなんだろうな、とか、この人が旦那さんで本当によかったな、とか、やっぱり楽しさをシェアしたいから作って楽しかったものは人にも見てもらいたいのかな、とかいろいろと考えたし、この会話も楽しかったのでシェアしたい、と考えた次第。
補足
この記事を書いていて疑問に思った点。
“12*11+12*11” “132 +132 “
ってなった時、空白はどう処理してたんですか?と訊いたところ「見なかったことにする!」という答えが。PascalでStringを扱うにはポインタを使ってリスト構造を作って、それを使うしかないんだけど、データは空でもポインタで辿ることが出来れば文字列は続いているという判断をして、「見なかったことにする!」を実現していたらしい。