2J INA
ina_job@hotmail.com | |
HomePage | http://www015.upp.so-net.ne.jp/ina/ |
Brainf*ckとBefungeという2つの言語について解説します。
作者はこれらの言語を実際に使うことをお勧めしません。
これらの言語は一般にプログラミングに使う言語(C,C++,Java,Pascal,etc...)と比べはるかに命令数が少なく、はるかにTrickyです。これらの言語が分からないから(またはあまりに面倒くさいから)といってコンピュータプログラミングのことを誤解しないようにしてください。
これらの言語は基本的な命令しか持たないため、ある種パズル的な思考を要求されます。まあ一種の知的な遊びとして捉えていただければ幸いです。
更に言うとこれらの言語のインタプリタ作成は他の言語に比べるととても簡単です。この言語に興味を持った方は是非一度作ってみてください。
ごめんなさい*は伏字です。
とりあえずこういった言語の代表格といえばこの言語。
有名なHelloWorldプログラムを見ることにしよう。
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>+++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.
実行結果
Hello World!
はい、勝手にやってろ! って感じですね。
いまさらながら文法解説します。
このプログラム言語は数値を記録できる無限長のテープがあって、そこを1つのポインタが指差しているようなイメージになっています。
> | ポインタを1進める |
< | ポインタを1戻す |
+ | ポインタのさす要素の値を1+する |
- | ポインタのさす要素の値を1-する |
. | ポインタのさす要素の値を出力 |
, | 外から値を入力してポインタのさす要素に入れる |
[ | ポインタのさす要素の値が0なら次の]に飛ぶ |
] | 対応する[までジャンプ |
上記以外の文字は無視するのが普通です
HelloWorldが分からない? ではちょっと「H」を出す部分を詳しく見てみましょうHのASCIIコードは&H48、まああえて10進表記すると72ですね。素直にソースにしよう。
++++++++++ ++++++++++ ++++++++++ +++++++++++ ++++++++++ ++++++++++ ++++++++++ ++ .
今回は10個ごとに区切ったので見やすいはず。しかし、こんな事していたんでは長すぎる
++++++++[>+++++++++<-]>,
72=9*8 ということで圧縮してみました。先に書いたHelloWorldプログラムでは<>の対応が逆だけどまあ基本は同じ
あまり有名どころではないが個人的に気に入っている言語です。2次元版Brainf*ckって所でしょうか。
なおここで解説するのはBefunge93です。より命令の増えたBefunge98というのも存在するが今回はそこまでは述べていません。
v >v"Hello world!"0< ,: ^_25*,@
先ほどのBrainf*ckよりは分かりやすそう。HelloWorldって書いてあるし。
この言語にはプログラムが現在どこまで進んでいるかを示すプログラムカウンタと80×25のプログラムコードを書く領域。さらにスタック式にデータを記録できるメモリ領域があるようなイメージです。
プログラムの解釈は左上から始まり右向きに解釈されます。
移動命令 | < ^ > v ? の5種類 初めの4つは向きをさす方向(←↑→↓)にプログラムの進行方向を変えます。?はランダムで進行方向を変えます。 |
数字リテラル | 0,1,2,...,8,9 の10文字が数値として認識可能。数値リテラルを解釈するとスタックにそれを詰め込みます。10以上の表現については後述 |
文字リテラル | "があると文字列モードに入ります。それ以降の文字のASCIIコードがスタックに入れられます。再び"を読み込むと文字列モードを終了します。 |
演算子命令 | + - * / % スタックの上2つの要素を取り出して演算してまたスタックに戻します。 |
入力命令 | & と ~ がある。 &は数値を受け取り解釈してスタックに入れます。 ~はその文字の文字コードをスタックに入れます。 |
出力命令 | .と, がある .はスタックの要素取り出してを数値として出力します。,はASCIIコードとして解釈しその文字を出力します。 |
終了命令 | @ です。この文字を読み込むとプログラムは終了します |
なおスペースはいくらあっても意味を成しません。
とりあえずここまでを頭に入れて次の例を見てください。
65+.@
11を出力します(6+5=11)
>5. v ^ <
永遠に5を出力します
v > 1 v > ? 2 v > 3 > .@
3面ダイスを振る
10以上の数を計算したい場合は0から9の値を演算して作り出してください。
37*5*@
スタックに105が入ります。(3*7*5=105)
これを利用して
& 37*5* * 55*4* / .@
入力された数値の105/100倍した値(税込価格)を表示
& 37* * 54* / .@
同じことだが21/20倍した値
~.@
入力された文字の文字コード表示
&,@
入力された文字コードに対応する文字を表示
もう少し高度な命令を
スタック操作命令 | \と$と:の3つ \は先頭のスタック2つを入れ替える。$はスタックの先頭の要素をを破棄する:はスタックの先頭の要素をコピーし更にスタックに詰めます。。 |
条件分岐命令 | _ と | がある。どちらの命令もスタックの要素をひとつ取り出して、 _は真(0以外)であれば<のように、偽の場合は>のように振舞う。|は真(0以外)であれば^のように、偽の場合はvのように振舞う。 |
5>::.v ^ -1_@
543210 と表示
(表示、条件分岐でもスタックからデータを取り出すため、:で複製しています。)
比較命令 | ` である。スタックの2つの要素を取り出して始めに取り出した数の方が大きければ真(0以外)小さければ偽(0)をスタックに入れる |
論理否定 | !である。 スタックの値を1つ取り出して真(0以外)なら偽(0)を偽(0)なら真(0以外)をスタックに入れる。 |
橋命令 | #である プログラムカウンタを進行方向に2進める。つまり、次実行すべき命令を1つ飛ばす。 |
プログラム改変命令 | g と pの2つ。gはスタックから2つ値をとる。その値をx,yとすると座標(x,y)に相当する部分のプログラムコードを返す。 pはスタックから3つ値を取り出す。その値をx,y,vとすると。座標(x,y)に相当するプログラムコードにASCIIコードvの文字を上書きする |
以上がBefungeの全命令です。
91+00p v >v"What's your name?"*250< > 0v ,: |!`p00:+1g00*88_24g00g4p0v ^_$ >~:00g4p25*- ^ >v"Hello, < ,: ^_$25*"!",,@
最後に大作を、名前を聞いてくるので入力すると「Hello ....」と返してくる(....は入力した名前)
特筆すべき点はこのプログラムの5行目が改変されて最終的な出力コードを得るということです。
何度も言うようだがこれらの言語はあまり実用性が無い。しかし、頭の体操に何か思いつく処理をさせる。プログラムの勉強にこれらのインタプリタを作る。などに向いていると思います。
興味を持った人は挑戦してみてください。