まるで暗号.今更ながら難読プログラミング言語Brainf*ckを解読してみる
Brainfuck
Brainfuckとは難読プログラミング言語(esolang: Esoteric Programming Language)と呼ばれ,いわゆる実用性を排除したユーモアプログラミング言語である.
実際に頑張って僕が書いた(超大事)「Hello,World!」を出力するコードを見てみると,
1 | +++++++++[>++++++++<-]>.<+++++++[>++++<-]>+.+++++++..+++.<+++++++++++[>------<-]>-.<+++++++++++[>++++<-]>-.<++++++[>++++<-]>.+++.------..--------.>+++++++++++[>+++<-]>. |
という感じになる.
見ただけでは何もわからない.(初見だと魚の骨にしか見えん)
これで,チューリング完全(一応なんでもプログラミングできる)なんだからすごい.
環境構築
必要ない人は読みとばしてくれ...
欲しい人は
http://esoteric.sange.fi/brainfuck/compiled/win/BFI.exe
からインタプリタをダウンロードすると良い.
24KBしかないから安心してくれ.
Brainfuckのインタプリタ
命令一覧
Brainfuckには8つの命令が存在する.
命令 | 意味 | C言語での同義 |
+ | ポインタの値をインクリメント | ++(*ptr); |
- | ポインタの値をデクリメント | --(*ptr); |
> | ポインタを右にインクリメント(移動) | ++ptr; |
< | ポインタを左にインクリメント(移動) | --ptr; |
[ | 現在参照中のポインタの値が0ならば ] まで移動 | while(*ptr){ |
] | 現在参照中のポインタの値が0でなければ [ まで移動 | } |
. | 現在参照中のポインタの値を出力 | print( *ptr ); |
, | 現在参照中のポインタに値を入力 | *ptr = getchar(); |
以上の8つの命令を用いて,プログラミングします.
これ以外の文字は全てコメントとみなされ無視されます.
簡易コードで理解する
まずは簡単なコードで理解していく.
1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. |
まずはこのコード,大文字の「A」を出力するコードである.
デフォルトでは最初に指しているポインタの値は0でなので,「+」を65回入力します.
そうするとASCIIコード65(10進数表記,16進数では41H)の「A」をポインタは指すようになります.
その後「.」で出力させているというわけです.
ちなみに「123」と出力させたいなら,
1 2 3 | +++++++++++++++++++++++++++++++++++++++++++++++++. +. +. |
こんな感じです.
ASCIIコード49の「1」を出力し,同じポインタをインクリメントして「2」にして出力,最後にもう一度インクリメントして「3」を出力する,といった具合です.
変数の扱い
Brainfuckでは変数のような処理も可能です.現在参照しているポインタをずらせばよいのです.
先程の「123」と出力するコードで,「1」と「2」と「3」をそれぞれ保っておきたい場合は
1 2 3 4 5 6 7 | +++++++++++++++++++++++++++++++++++++++++++++++++ # [ 1 | | | ] > # 右にポインタをずらす ++++++++++++++++++++++++++++++++++++++++++++++++++ # [ 1 | 2 | ] > # 右にポインタをずらす +++++++++++++++++++++++++++++++++++++++++++++++++++ # [ 1 | 2 | 3 ] <<. # 最初のポインタに戻して出力 >.>. # 右にずらして出力,右にずらして出力 |
こう書けばよいということです.
これで配列には[1|2|3]という値が格納されていることになります.
しかし,なんだか冗長ですね...
(Brainfuckだから仕方がないとか言わない)
ループで綺麗に
ASCIIコードにおいて,数字の0は48から始まります.
もし,それ以前の記号を使わないのであれば,毎回「+」を40回以上打ち込むのは無駄です.
ということで,ループ命令を使ってスマートに書き換えましょう.
1 2 3 4 5 6 | ++++++++++++ # これはループカウンタ [ >++++ # ポインタを右にずらして4つ足す <- # ループカウンタをデクリメント ] >+.+.+. # 出力 |
なにやらBrainfuck感が出てきました!
我ながら書けるようになってくるとワクワクしてきます!笑
Hello,World!
さて,いよいよ「Hello,World!」に挑戦です.
1 2 3 4 5 6 7 8 9 10 11 | +++++++++[>++++++++<-]>. # H <+++++++[>++++<-]>+. # e +++++++.. # ll +++. # o <+++++++++++[>------<-]>-. # , <+++++++++++[>++++<-]>-. # W <++++++[>++++<-]>. # o +++. # r ------.. #ll --------. # d >+++++++++++[>+++<-]>. # ! |
最後の「!」だけ,ポインタを最初から動かしています.
最終的な配列は
[ 0(ループカウンタ) | d | 0(ループカウンタ) | ! ]
という感じかな?
確かめてないので間違っているかも.
ちなみにHello,World!コードを可視的に分かりやすく解説しているのは以下のサイト.
https://fatiherikli.github.io/brainfuck-visualizer/
さいごに
Brainfuck難しいようで,意外と書けるようになるもんですね.「実験の待ち時間あるから,Brainfuckでも理解してみるかー」と思い立って,そんなにかからず理解できました.
ただ,ASCIIコード表がないと,書けないですこれ.
他にもジョークプログラミング言語がありますが,たぶん解読するのはBrainfuckが最初で最後な気がします.
Brainfuck派生のOok!とかはたぶん書けるけど,解読はしたくない...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook. Ook! Ook. |
おわり.