今日から毎日brainをf*ckしよう
※脳姦の話ではありません。
brainf*ckってのはプログラミング言語の名前です。所謂「難解プログラミング言語」と呼ばれるプログラミング言語の一種で「コンパイルが楽な言語」として開発されたらしいです。その代わり「分かりやすさ」という部分はバッサリ切り捨ててあります、
まぁググれば出て来るんですが、とりあえず言語仕様から解説していきましょう。
この言語に使われる記号は8種類しかありません。その8種類をひたすらつないでいくだけの言語です。8種類の記号とその意味は以下のとおりです。
> | ポインタを1つ進める |
---|---|
< | ポインタを1つ戻す |
+ | ポインタの指している部分の値に1加える |
- | ポインタの指している部分の値に1引く |
[ | ポインタの指している値が0の時 対になる]の直後まで移動 |
] | ポインタの指している値が0以外の時 対になる[の直後まで移動 |
. | ポインタの指している値を文字として表示 |
, | 標準入力から1バイト読み取ってその値をポインタの指している場所に代入 |
「これだけで何をしろって言うんだ……」と思われるかもしれませんが、理論上はこの8種類の記号からなる記号列だけでどんなプログラムでも作れることになってます(チューリング完全 - Wikipedia)。
じゃあまぁとりあえず実際に書いて覚えよう。インタプリタはこの辺にある→
BrainFuckインタープリタ:いで庵
,[>+>+>+<<<-]>->>+<<[,>]
初期状態としてメモリは全て0にセットされていてポインタはその先頭を指している。
つまりこんな感じ
0 | 0 | 0 | 0 | 0 | 0 | 0 | …… |
---|
先頭には","があるのでまず入力から一バイトだけ取ってくる。さっきのインタプリタだと文字の入力を求められる。とりあえず"b"を入力したことにしよう。
98(b) | 0 | 0 | 0 | 0 | 0 | 0 | …… |
---|
次の記号は"["だが、現在ポインタの指している箇所の値は0じゃないのでこれはスルー。次に">"があるのでポインタが右へ1つ動く。その次が"+"なのでそこに1を足す。つまりこうなる。
98(b) | 1 | 0 | 0 | 0 | 0 | 0 | …… |
---|
この後">+"をもう2回繰り返すのでこう。
98(b) | 1 | 1 | 1 | 0 | 0 | 0 | …… |
---|
そして"<"を3回繰り返すのでポインタが丁度元の位置に戻る。
98(b) | 1 | 1 | 1 | 0 | 0 | 0 | …… |
---|
更に"-"でそこの値から1引く。
97(a) | 1 | 1 | 1 | 0 | 0 | 0 | …… |
---|
次に"]"が来るがポインタの値は0ではないのでちょっと前に出て来た"["まで巻き戻る。つまり「最初に入力した値の隣3つに1を加え最初に入力した値からは1を引く」ということをグルグル回って繰り返すわけだ。グルグル回ってる内にいつしかこういう状態になる。
0 | 98(b) | 98(b) | 98(b) | 0 | 0 | 0 | …… |
---|
元の数は0になり代わりに98(bを示すアスキーコード)が隣に3つ並んでいる。この状態で"]"に来た時初めてループを抜け出すことになる。
その次は">->>+"。日本語にすると「1個進んで1を引き、2個進んで1を足す」となる。(※ちなみにスタート地点はループを抜けた直後なので先頭の0の位置であることをお忘れなきよう)
0 | 97(a) | 98(b) | 99(c) | 0 | 0 | 0 | …… |
---|
そして"<<"。
0 | 97(a) | 98(b) | 99(c) | 0 | 0 | 0 | …… |
---|
次"["。ループの始まりだ。当然0ではないので最初は普通にループの中に入る。
ループの中一番目は"."。これは文字を表示するコマンド。メモリの内容は97だがこれはaを示すアスキーコードなのでaが表示される。(ちなみにメモリの内容を整数として表示するコマンドは存在しないので 数値を表示させたいならまた一工夫必要だ。)
0 | 97(a) | 98(b) | 99(c) | 0 | 0 | 0 | …… | ※文字を表示しただけなのでメモリの内容はは変化していない |
---|
その次は">"でポインタを1つずらす。
0 | 97(b) | 98(b) | 99(c) | 0 | 0 | 0 | …… |
---|
ループの終わり"]"だが0ではないのでループは存続する。
というわけでループの先頭に戻りbを表示してポインタを1進めることになる。
0 | 97(b) | 98(b) | 99(c) | 0 | 0 | 0 | …… |
---|
ここも0ではないので更にループを繰り返す。cという文字が表示される。
0 | 97(b) | 98(b) | 99(c) | 0 | 0 | 0 | …… |
---|
というわけでようやく0に到着したのでループは終わりプログラムも終了だ。そして標準出力には"abc"という文字列が表示されている。
とまぁこんな具合なことを繰り返すのがbrainf*ckだ。どうだい?楽しいだろう?これでHelloWorldを表示するためには律儀に全ての文字のアスキーコードを+で生成する必要がある。FizzBuzzを実行したかったらまずメモリの値を10進数として表示するプログラムを書くところから考えなければならない。実にややこしい。でもそれが
✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
次はbrainf*ckで作ったFizzBuzzとQuineを紹介するかな。