ASCIIコード表出力プログラム

初めに

BFで"L"って出力したいなぁ。"L"ってASCIIコードで何番だっけ?

せっかくだからBFでASCIIコード表出力プログラムを作ってそれを見よう。

ソース

-[>+.<-]
説明
ポインタが指しているメモリの数値が0の時、デクリメントするとそこの値は255になる。なのでこれは255回ループし出力している。

おそろしく短いですね。でもこれ実行してみると分かるんですけど、とても分かりづらいんですよね。なので分かりやすい物を作りました。

++++++[>>>>++++++++>++++++++>++++++++<<<<<<-]
>>>++++++++++<<<++++++[>>>>>>>++++++++++<<<<<<<-]
>>>>>>>+<<<<<<<++++++[>>>>>>>>>>>>+++++++++<<<<<<<<<<<<-]
>>>>>>>>>>>>++++<<<<<<<<<<<<>-[>>>>>+>>[-]>[-]<<<[>>+>+<<<-]
>>>[<<<+>>>-]>[-]>[-]>[<+<+>>-]<[>+<-]>>[-]+<<<[-<<->>]<<[>>>>>-<<<<<[-]]
>>[>>>-<<<[-]]>>>[[-]<<<<<<<[-]<<<<<<++++++[>>>>>>++++++++<<<<<<-]>>>>>+>>>
[-]>[-]<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]>[-]>[-]>[<+<+>>-]<[>+<-]>>[-]+<<<[-<<->>]
<<[>>>>>-<<<<<[-]]>>[>>>-<<<[-]]>>>[[-]<<<<<<<<[-]<<<<<++++++
[>>>>>++++++++<<<<<-]>>>>+>>>>>>>>>]]<<<<<<<<<.>.>.>.<<<<<+.>.<<-]

おそろしく長いですね。BFでこんなに長いと何がなんだかまったくわかりません。というわけで、コメントをつけてみました。

#1          = LoopCounter
#2          = ItemLoopCounter
#3          = ItemData
#4          = ConstNewLineCode(0x0A)
#5:6:7      = ItemCounter
#8          = ConstEqual(0x3D)
#9:10:11:12 = Temp
#13         = ConstMaxItemCounterSize(10::0x3A)
#14         = IfFlag

#Initialize ItemCounter(000::0x30:0x30:0x30)
++++++[>>>>++++++++>++++++++>++++++++<<<<<<-]

#Create ConstNewLine(0x0A)
>>>++++++++++
<<<
#Create ConstEqual(0x3D)
++++++[>>>>>>>++++++++++<<<<<<<-]>>>>>>>+
<<<<<<<
#Create ConstMaxItemCounterSize(10::0x3A)
++++++[>>>>>>>>>>>>+++++++++<<<<<<<<<<<<-]>>>>>>>>>>>>++++
<<<<<<<<<<<<

#Set ItemLoopCounter To Max(255::0xFF)
>-

#Start Output Item
[
    #ItemCounter3 Process
    >>>>>+                              #Increment ItemCounter3
    >>[-]>[-]                           #Temp1 Temp2 Clear
    <<<[>>+>+<<<-]                      #Copy ItemCounter3 To Temp1 Temp2 And ItemCounter3 Clear
    >>>[<<<+>>>-]                       #Copy Temp2 To ItemCounter3
    
    >[-]>[-]                            #Temp3 Temp4 Clear
    >[<+<+>>-]                          #Copy ConstMaxItemCounterSize To Temp3 Temp4 And ConstMaxItemCounterSize Clear
    <[>+<-]                             #Copy Temp4 to ConstMaxItemCounterSize
    
    >>[-]+                              #IfFlag On
    <<<                                 #Position Temp3
    [-<<->>]<<                          #=========================
    [>>>>>-<<<<<[-]]>>                  # If Temp1 *EQ Temp3 Then
    [>>>-<<<[-]]>>>                     #=========================
    [
        [-]                             #IfFlag Off
        <<<<<<<[-]                      #Set ItemCounter3 To 0(0x00)
        <<<<<<                          #Position LoopCounter
        ++++++[>>>>>>++++++++<<<<<<-]   #Initialize ItemCounter3(0::0x30)
        
        #ItemCounter2 Process
        >>>>>+                          #Increment ItemCounter2
        >>>[-]>[-]                      #Temp1 Temp2 Clear
        <<<<[>>>+>+<<<<-]               #Copy ItemCounter2 To Temp1 Temp2 And ItemCounter2 Clear
        >>>>[<<<<+>>>>-]                #Copy Temp2 To ItemCounter2
        
        >[-]>[-]                        #Temp3 Temp4 Clear
        >[<+<+>>-]                      #Copy ConstMaxItemCounterSize To Temp3 Temp4 And ConstMaxItemCounterSize Clear
        <[>+<-]                         #Copy Temp4 to ConstMaxItemCounterSize
        
        >>[-]+                          #If Flag On
        <<<                             #Position Temp3
        [-<<->>]<<                      #=========================
        [>>>>>-<<<<<[-]]>>              # If Temp1 *EQ Temp3 Then
        [>>>-<<<[-]]>>>                 #=========================
        [
            [-]                         #If Flag Off
            <<<<<<<<[-]                 #Set ItemCounter2 To 0(0x00)
            <<<<<                       #Position LoopCounter
            ++++++[>>>>>++++++++<<<<<-] #Initialize ItemCounter2(0::0x30)
            >>>>+                       #Increment ItemCounter1
            >>>>>>>>>                   #Position IfFlag
        ]
        
    ]
    
    #Output Process
    <<<<<<<<<.                          #Output ItemCounter1
    >.                                  #Output ItemCounter2
    >.                                  #Output ItemCounter3
    >.                                  #Output ConstEqual
    <<<<<+.                             #Increment ItemData And Output ItemData
    >.                                  #Output ConstNewLine
    <<-                                 #ItemLoopCounter Decrement
]

数字の繰り上がり処理を作るのに苦労しました。

説明はそのうち書くかもしれません。ちなみにここに書いてある英語みたいなのは、めちゃめちゃ適当に書いたものです。偽英語ですね。

ちなみに、同様の出力結果になるプログラムをCで書いてみると以下のようになります。

#include <stdio.h>
int main() {
    for (int i = 0;i < 255;i++) {
        printf("%03d=%s\n", i, (char *)&i);
    }
    return 0;
}

ちょっと追記

数値が0の時のデクリメントは、処理系によっては255にならない場合があります。1バイトが9bitだったり、0の時にデクリメントするとエラーになるように作られていたり…。その辺を頭に入れておいてください。

2004/05/19追記

BrainFuck ENSI規格によると、

Cells can hold values from 0 to 255.

訳:セルは0〜255に値を固定することができます。

となってました。

canは酷いだろ、っつーかこの訳あってんのか?

まぁそれはいいとして、255の値をインクリメントしたら0にしてはいけないとか、0の値をデクリメントしたら255にしてはいけないとか、そんなことは書いてないようです。そのかわり0〜255に固定するのはやってもよさそうな感じですね。でも「固定することができます」だからなんとも言えないけど…。

2004/06/03追記

上記のものはBrainFuck ENSI規格というよりは、BrainFuckGolfのルールでした。まぁいいや。

そのルールの中に、

No over- or underflow allowed.

訳:オーバーまたはアンダーフローは許可されません。

ってのもありました。

えーっとどういうことだ?許可されないってどういう風にとればいいんだ?エラーにしろって事か?255を越えずに固定にするって事か?255を超えたら0にするって事か?もう少し調べてみよう。

2004/10/27追記

上のものは単純にBrainFuckGolfに投稿されるプログラムではオーバーアンダーフローを使用しちゃいけないってだけですね。

なんでそんな単純なことに気づかないんだ…私は…。