Befungeでのプログラミングのコツを紹介します。
とりあえず、基本の文字列を表示する方法です。Befungeには、,(コンマ)と.(ピリオド)の二種類が、出力する命令としてあります。.(ピリオド)は数字しか出力できないので、基本は,(コンマ)を使って文字列を出力していくことになります。このコンマは、「スタックをポップして、それをASCIIコードにもつ文字を1文字出力する」というものです。つまり、文字列を出力するには、まずスタックに文字列のASCIIコードを積んで、その後文字数のぶんだけコンマを置いておけばいいのです。
ところで、スタックに文字列のASCIIコードを積むというのが大変な作業なようですが、専用の命令があります。 " 〜 "です。これで囲まれた間は、その文字のASCIIコードがスタックに積まれていきます。
つまり、例えば"Hello"と出力したければ、
>"olleH",,,,,@
とすればいいことになります。
ここで、"〜"の間が逆になっていますが、これは、スタックに積んだとき(プッシュしたとき)、後に積んだものほど上になりますが、スタックから取り出すとき(ポップするとき)は上から順に取り出すからです。つまり、今回文字列の最後がHですから、最初に,(コンマ)で取り出されるのがHということになり、これで正しいのです。
さて、同じ理屈で"Hello, world!"を出力したければ
>"!dlrow ,olleH",,,,,,,,,,,,,@
とすればよいことになります。
しかし、これではコンマが並んで格好が悪いですね。ここで登場するのがループです。
>0"!dlrow ,olleH">:v
^,_@
さっきと変わっている点は、"〜"でASCIIコードをスタックに積む前に0をスタックに積んでいるということです。これは一番下にきます。0を文字列の終端として、ここまでを文字列とすることで、任意の長さの文字列に対応しようという魂胆です。
その後のループの本体は、
>:v
^,_@
の部分です。_(アンダーバー)は、スタックをポップして、0なら右、それ以外なら左というものでした。右に行くと@(終了)です。左に行くと,(ポップして出力)なので、0以外なら、終了してまたループするということになっています。さて、_の前に:(コロン)があります、これは、スタックをポップして2回プッシュ、すなわちスタックの一番上を2つに増やすということです。なぜこれをするかというと、_でスタックがポップされると、その値は戻ってきません。ある値について判定したあと、さらに使いたい場合(今回の場合、_で判定した後,で使っています)には、あらかじめ:を使って2つに増やしておかないといけないのです。
このようにすれば、文字列の長さがどうであっても表示できます。これを利用して、サンプルの99 Bottles of Beer.txtでは、異なる文字列を同じループで表示しています。逆に、コンマをいくつも並べて表示する例としては、サンプルのFizzBuzz.txtがあります。
また、#(シャープ)を有効活用すれば、1行でループを表現できます。
>0"!dlrow ,olleH">:#,_@
これは、最初に0とASCIIコードをスタックに積むところは同じです。ループの本体は、
>:#,_@
という部分になります。1つあるシャープが鍵です。左から右へ行くときは、まず:(コロン)で先頭を2つに増やしたあと、シャープで,(コンマ)を飛ばして_(アンダーバー)にたどり着きます。ここで0なら、右へ行って終了ですね。0以外なら、左へ行きます。さっき飛ばした,(コンマ)によって1文字出力し、今度は:(コロン)を飛ばしてまた左向きになります。
1桁の数は、0〜9の命令によってスタックに積むことができます。では、複数桁の数はどうでしょう。これを直接行う命令はないですが、これは1桁の数の計算によって実現します。例えば、25*
とすると、最終的にスタックに10が積まれた状態になります。+ - * / %の四則演算の命令は、スタックの上2つを計算によって1つにまとめてしまいますから、ここで5*
というのはセットで「スタックの一番上に5をかける」ととることもできます。そうすると、まず2を積んで、それに5を掛けて10になった、と考えることができます。慣れてくると、例えば55*4*
という命令群が、「100をスタックにつむ」という1つの命令に見えてきます。
これは、どのような計算をすれば目的の数字をスタックに積めるかを自分で考えて作る必要があります。例えば「123」なら、123=41*3=(5*8+1)*3だから
58*1+3*
とできます。あるいは、123=125-2=5*5*5-2だから
55*5*2-
としてもよいでしょう。3*5*8+3だから
35*8*3+
というのもありです。これらはたまたまどれも長さが同じですが、美しいBefungeプログラムということを視野にいれて作るとよいでしょう。
Befungeなどの難解プログラミング言語では、プログラムの美しさを向上するというのも楽しみ方のひとつです。
例えば、単純なものでは、横に進む部分と縦に進む部分が、ある共通な文字で交差するようにすると、その文字は異なる役割で2回使われることになります。サンプルのHelloWorld.txtでは、(5, 3)のlと(7, 3)のoと(10, 6)の, の3箇所でこれを行っています。
また、なるべく小さくまとめるというのも方向性の1つです。作者にはまだそういった技術がないので、サンプルのプログラムはどれもスカスカで穴があいています。この穴を無くして、中身の詰まったBefungeプログラムを作るというのもよいでしょう。