Edited at
LIFULLDay 13

Brainfuck 超入門

LIFULL Advent Calendar 2018の13日目です。

どんなことを書こうか悩んだ挙句、Brainf*ckの事でも書こうかなと思い立ちました。

なぜBrainf*ckなのかと言うと、面白いから。以上です。

特に深い理由もなくBrainf*ckのソースコードを書いて何かするのが楽しいので、

それを他の人にも共有できれば良いかなと

とりあえずBrainf*ckの入門書的なものを書こうと思います。

この記事を読んだみなさんがBrainf*ckへの興味を持ってくれると嬉しいです。


Brainfuckとは

プログラミング言語です。

また、難解プログラミング言語(esolang)の代表格です。

Brainf*ckのように伏字で表記されることもあります。あんまりf*ckだらけになってもあれですしね。

後述しますが、実行できる命令が8種類しかありません。

実用性は皆無です。とても特徴的な言語です。


言語の仕様

さっそく実装に移りたいですが、その前に仕様を確認しましょう。

Brainfuckでは配列が用意され、その配列の要素を指すポインタと要素の値を操作していきます。

また、Brainfuckには以下の8種類の命令しかありません。

その他の文字は無視されます。

リファレンスを漁る必要がないですね。

文字
動作

>
ポインタをインクリメント (右にずらす)

<
ポインタをデクリメント (左にずらす)

+
ポインタの値をインクリメント

-
ポインタの値をデクリメント

.
ポインタの値を出力

,
入力から1バイト読み込んで、ポインタが指す値に代入

[
ポインタの指す値が0なら、後の]までジャンプ(要するにwhile)

]
ポインタの指す値が0でなければ、前の[までジャンプ


実行環境

まずはBrainfuckの実行環境です。

こんなものもあったりしますが、

おもむろに

$ brew install brainfuck

を実行します。

するとBrainfuckのインタプリタが使えるようになります。

インタプリタについての詳しいことは、↓です

https://github.com/fabianishere/brainfuck

さて、お待ちかねのソースコードを書きましょう。


まずは簡単にABCと出力するコードから


abc.bf

++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++++.+.+.>++++++++++.

そして実行

$ brainfuck abc.bf

ABC

簡単ですね。

簡単ですが、少し解説すると、

1行目は+が40文字あるので、ポインタの指す値を40回インクリメント

2行目も最初の方で+によって25回インクリメントしているので、

ポインタの指す値は65になっています。

その後の.によって出力されるのでAが出力されます。(ASCIIコードの65はAです)

そして+.が連続で実行されるのでBCが出力されます。

最後の方で>によってポインタを1つずらして(ポインタの指す値は0になります)、値を10回インクリメントして出力(改行を出力)しています。


Hello World! してみる

さて、プログラミングといえばHello World!ですよね。

ということでやってみます。

上で書いたABCを出すコードは本当に入門というか効率が悪いコードだったので、

今度は[]を使って効率を考えてコードを書いてみます。

コードはこちら


hello_world.bf

+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.

>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.

一気にBrainfuck感がでました。

そして実行結果

$ brainfuck hello_world.bf

Hello World!

ここまでくればもう立派なBrainfuckerですね。

Hello World!のコードを全部解説すると長くなるので、

[]についてだけ少し解説しようかと思います。

[]はwhile文に相当するものです。

次のコードがあったとします。

[+]

これをC言語で表現すると、


while(*p) {
(*p)++;
}

このようになります。

要するに現在のポインタの指す値にインクリメントし続けるコードです。

次のコードはどうでしょう

+++[-]

これは、書き下すと少しわかりやすくなるかもしれません

+++

[
-
]

C言語で書くと

(*p)++;

(*p)++;
(*p)++;
while(*p) {
(*p)--;
}

のように表せます、あってますかね?

動作の説明がしづらいですが、簡潔にまとめると、3回回るfor文です。

ここで、もう一度コードに戻りましょう。

もうどんなことをやっているのか読めるようになっているはず!


hello_world.bf

+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.

>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.

1行目の+++++++++[>++++++++>+++++++++++>+++>+<<<<-]の部分で9回ループを回してその中でインクリメントすることで、9×N回のインクリメントを済ませます。

その後はよしなにして出力するだけですね。


最後に

Brainfuckの面白さを伝えきれていない感がありますが、大丈夫ですかね。

基本的な処理の流れさえわかってしまえば、パズルのように実装できるので、ハマると面白いです。

ぜひ皆さんもBrainfuckerになってみてください。


参考サイトとか