LIFULL Advent Calendar 2018の13日目です。
どんなことを書こうか悩んだ挙句、Brainfckの事でも書こうかなと思い立ちました。
なぜBrainfckなのかと言うと、面白いから。以上です。
特に深い理由もなくBrainf*ckのソースコードを書いて何かするのが楽しいので、
それを他の人にも共有できれば良いかなと
とりあえずBrainfckの入門書的なものを書こうと思います。
この記事を読んだみなさんがBrainfckへの興味を持ってくれると嬉しいです。
Brainfuckとは
プログラミング言語です。
また、難解プログラミング言語(esolang)の代表格です。
Brainfckのように伏字で表記されることもあります。あんまりfckだらけになってもあれですしね。
後述しますが、実行できる命令が8種類しかありません。
~~実用性は皆無です。~~とても特徴的な言語です。
言語の仕様
さっそく実装に移りたいですが、その前に仕様を確認しましょう。
Brainfuckでは配列が用意され、その配列の要素を指すポインタと要素の値を操作していきます。
また、Brainfuckには以下の8種類の命令しかありません。
その他の文字は無視されます。
リファレンスを漁る必要がないですね。
文字 | 動作 |
---|---|
> | ポインタをインクリメント (右にずらす) |
< | ポインタをデクリメント (左にずらす) |
+ | ポインタの値をインクリメント |
- | ポインタの値をデクリメント |
. | ポインタの値を出力 |
, | 入力から1バイト読み込んで、ポインタが指す値に代入 |
[ | ポインタの指す値が0なら、後の]までジャンプ(要するにwhile) |
] | ポインタの指す値が0でなければ、前の[までジャンプ |
実行環境
まずはBrainfuckの実行環境です。
こんなものもあったりしますが、
おもむろに
$ brew install brainfuck
を実行します。
するとBrainfuckのインタプリタが使えるようになります。
インタプリタについての詳しいことは、↓です
https://github.com/fabianishere/brainfuck
さて、お待ちかねのソースコードを書きましょう。
まずは簡単にABC
と出力するコードから
++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++.+.+.>++++++++++.
そして実行
$ brainfuck abc.bf
ABC
簡単ですね。
簡単ですが、少し解説すると、
1行目は+
が40文字あるので、ポインタの指す値を40回インクリメント
2行目も最初の方で+
によって25回インクリメントしているので、
ポインタの指す値は65になっています。
その後の.
によって出力されるのでA
が出力されます。(ASCIIコードの65はA
です)
そして+.
が連続で実行されるのでBC
が出力されます。
最後の方で>
によってポインタを1つずらして(ポインタの指す値は0になります)、値を10回インクリメントして出力(改行を出力)しています。
Hello World! してみる
さて、プログラミングといえばHello World!ですよね。
ということでやってみます。
上で書いたABCを出すコードは本当に入門というか効率が悪いコードだったので、
今度は[]
を使って効率を考えてコードを書いてみます。
コードはこちら
+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.
>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.
一気にBrainfuck感がでました。
そして実行結果
$ brainfuck hello_world.bf
Hello World!
ここまでくればもう立派なBrainfuckerですね。
Hello World!のコードを全部解説すると長くなるので、
[]
についてだけ少し解説しようかと思います。
[]
はwhile文に相当するものです。
次のコードがあったとします。
[+]
これをC言語で表現すると、
while(*p) {
(*p)++;
}
このようになります。
要するに現在のポインタの指す値にインクリメントし続けるコードです。
次のコードはどうでしょう
+++[-]
これは、書き下すと少しわかりやすくなるかもしれません
+++
[
-
]
C言語で書くと
(*p)++;
(*p)++;
(*p)++;
while(*p) {
(*p)--;
}
のように表せます、あってますかね?
動作の説明がしづらいですが、簡潔にまとめると、3回回るfor文です。
ここで、もう一度コードに戻りましょう。
もうどんなことをやっているのか読めるようになっているはず!
+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.
>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.
1行目の+++++++++[>++++++++>+++++++++++>+++>+<<<<-]
の部分で9回ループを回してその中でインクリメントすることで、9×N回のインクリメントを済ませます。
その後はよしなにして出力するだけですね。
最後に
Brainfuckの面白さを伝えきれていない感がありますが、大丈夫ですかね。
基本的な処理の流れさえわかってしまえば、パズルのように実装できるので、ハマると面白いです。
ぜひ皆さんもBrainfuckerになってみてください。
参考サイトとか
-
https://fatiherikli.github.io/brainfuck-visualizer/
- Brainfuckのインタプリタです
- 動作の流れがとてもわかりやすいです
-
https://esolangs.org/wiki/Brainfuck_algorithms
- Brainfuckで実装したアルゴリズム集です