はじめに
こんにちは!Life is Tech!でメンターをしているえーえすです!
今回はLife is Tech ! Kanto Advent Calendar 2022の10日目!昨日はGeekさんのF1激アツ記事でしたね!F1めっちゃみてみたくなりました!!
さて、僕はこのアドカレにこれ含めて3記事を投稿するんですが、他2記事がすっごい真面目なんです。だからこそ、この記事くらいはふざけたい!ということで!!
Brainf*ckで足し算ができる電卓を作ってみました!!
すっっっっっっごい頑張ったので是非読んでいただけると嬉しいです。
Brainf*ckって何?
Brainf*ckは、たった8文字しか使えないプログラミング言語です。は??って感じでしょうから、使える文字の一覧を載せておきます。
文字 | 意味 |
---|---|
> | ポインタをインクリメント |
< | ポインタをデクリメント |
+ | 今いるポインタの値をインクリメント |
- | 今いるポインタの値をデクリメント |
[ | 今いるポインタの値が0なら、対の]にジャンプ |
] | 今いるポインタの値が0でないなら、対の[にジャンプ |
. | 今いるポインタに入力を1バイト分取り込む |
, | 今いるポインタの値を出力 |
Brainf*ckでは、Int型の配列が用意されており、その要素にポインタを用いてアクセスできるといった感じに思っていただければ大丈夫です。詳しい内容はこちらの記事などが超絶参考になります。(なんと環境設定の話までしてくれています)数学に詳しい方なら、チューリングマシンとよく似たものだと思っていただければ大体のイメージがつくかと思います。
今回使わせていただいた環境
今回はTry It Onlineを使わせていただきました。なんでBrainfuckまで使えるの
やってみよう!
さて、この程度の軽い解説でも理解することはできたんじゃ無いかなと思います。ということで実際に書いてみましょう。最初は定番の「Hello, world!」から。
入力・出力はchar型として扱われるので、例えばHを出力したければ今いるポインタの値を72にすればいいということです。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+++++++++++++++++++++++++++++.
+++++++..
+++.
-------------------------------------------------------------------.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
--------.
+++.
------.
--------.
-------------------------------------------------------------------.
また、[]を用いることで反復を多少楽にすることができます。
++++++++[->+++++++++<]>.<+++++[->+++++<]>++++.+++++++..+++.<+++++++++[->---------<]>++.<+++++++++[->+++++++++<]>++++++.--------.+++.------.--------.<++++++++[->--------<]>---.
…さあ、こういう言語です。名前通り頭がクソになります。楽しくなってきましたね。
僕はこの言語を使って足し算を実装してみたくなりました。そこで今流行りのChatGPTに作り方を聞いてみたんですよ。そしたらできませんって返ってきたんです。作るしかねぇよなぁ!!!!
足し算を作ってみよう
最初に思い浮かぶのはこんな実装です。
2つのポインタに数を格納
↓
片方にもう片方のポインタの値をうつす
↓
出力
ここで、もう片方のポインタの値をうつす際、'0'のASCII値、48が余分に足されてるので、48引いてみたらいい感じになりそうですね。
,>, //(0)、(1)に数を格納
[<+>-] //(1)が0になるまで(1)をインクリメント、(0)をデクリメント
<------------------------------------------------ //(0)から48を引く
. //出力
また、入力も1バイトごとに読み込まれるので「1+1」のようにかけませんね。「11」と書くしかありません。
…そう。勘の言い方ならお気づきでしょうが、これでは繰り上がりのある計算や2桁以上の計算ができないわけです。電卓として致命的ですね??
ちゃんと足し算電卓を作ろう
先に謝らなければならないことがあります。この電卓は未完成で、桁数の大きい数を先に入力しないとぶっ壊れます。アドカレ間に合わなかったので許してください
さて、方針です。
+で区切った2つの数字を桁ごとに格納
↓
1つ目の入力の方に桁ごとに数を足していく
↓
繰り上がりの処理をする
↓
出力
格納まではよかった。その後が、ほんとに、地獄だった。
完成品
こちらとなっております。
-------------------------------------------[+++++++++++++++++++++++++++++++++++++++++++>,-------------------------------------------]
>
>,[>,]
<
[
[->+<]
>[<<[<]<[<]<+>>[>]>[>]>-]
<<[<]<[<]<[->+<]
>------------------------------------------------
[>]>[>]<
]
<[<]<[[->+<]<]
>>[>]<
[
-----------------------------------------------
[<]<++++++++++
[
-
>>[>]>+>>+<<
<<-[>>-<]>>[<<<[<]<[-]>>[>]>>->]
<<<<[<]<
]
>>[>]>>>>[>]<[<]<<<[[>>>>[-]<<<<[>>>>+<<<<-]]<+>]
>>>>+++++++++++++++++++++++++++++++++++++++++++++++
<<<<+<-[+>->]>[<+++++++++++++++++++++++++++++++++++++++++++++++++>->>]
<<<
]
>>>>>[.>]
ちゃんと計算ができます。なんなら普通の電卓よりでかい桁でもできる。
なにをしているのか
今回の製作で気づいたことは、[]をうまく使えば世界が変わるということです。こいつらをうまく使ってif文のような条件分岐だったり例外処理のつじつま合わせなどをすることができてしまうんです。(これ全部自分で考えたんですよ???褒めて欲しい)
-------------------------------------------[+++++++++++++++++++++++++++++++++++++++++++>,-------------------------------------------]
>
>,[>,]
<
ここの上1行で「入力が+になるまで入力、>」、その後の行で、「合わせて2つ空白を開け、入力が\0になるまで入力、>」をしています。]が呼ばれる時にいるポインタの値が0であるかどうか、というのをうまく使っています。
[
[->+<]
>[<<[<]<[<]<+>>[>]>[>]>-]
<<[<]<[<]<[->+<]
>------------------------------------------------
[>]>[>]<
]
ここでは、「うまく空白を開けながら一桁ごとに足し合わせ、保存」というのをやってますね。[<]とか[>]とかで次の空白まで飛んでいけるわけですから、これがすっごい便利だった。データの保存は0をうまく挟みながらまとめるという感じでやってるのもわかっていただけると嬉しいな。
<[<]<[[->+<]<]
ここで1つ目の入力の数で、足し合わされなかった分の桁を、足した後保存してあるところに合流させてます。
>>[>]<
[
-----------------------------------------------
[<]<++++++++++
[
-
>>[>]>+>>+<<
<<-[>>-<]>>[<<<[<]<[-]>>[>]>>->]
<<<<[<]<
]
>>[>]>>>>[>]<[<]<<<[[>>>>[-]<<<<[>>>>+<<<<-]]<+>]
>>>>+++++++++++++++++++++++++++++++++++++++++++++++
<<<<+<-[+>->]>[<+++++++++++++++++++++++++++++++++++++++++++++++++>->>]
<<<
]
ここで繰り上がり処理をしています。特に5+5みたいに入力のない桁に繰り上がるときの処理がもうほんとにむずかった……いい処理がきっとあるんでしょうが、これを思いついたのが天才。すごい俺。
要するにif(x>9)
みたいな条件を作ってるんですが、これがほんとにむずかしい。不等号ってこんなにもむずかったんですね………
>>>>>[.>]
最後に全部の桁を出力して、完成!!
おわりに
もうね、ほんとに大変だった。一晩寝たらこのコードがなんだったのかもうわからなくなってるんですよ。読めない。だから辛い。でも全てを理解して完成した時はほんとに嬉しかった。すごくいい経験でした。
こんな最高の言語、Brainf*ckですが、世界にはやっぱりえげつない人々がおりまして、BrainfuckでBrainfuckのコンパイラを書くみたいな、え、もうなんなんそれみたいなことやってる人がいたり。世界は広い。
ちなみにこの言語、チューリング完全だそうで、要するにどんなコードでも実行できます。みんなもやってみてね!
さてさて明日12/11のアドカレはこすさんの記事です!!とっても面白そうなので楽しみにしています!!!