Help us understand the problem. What is going on with this article?

Brainfuck 超入門

More than 1 year has passed since last update.

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になってみてください。

参考サイトとか

lifull
日本最大級の不動産・住宅情報サイト「LIFULL HOME'S」を始め、人々の生活に寄り添う様々な情報サービス事業を展開しています。
https://lifull.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした