Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling loops in Brainf*ck

Tags:

c

loops

brainfuck

I tried testing my Brainfuck interpreter in c with this bottle shaped code in Brainfuck:

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

And instead ouf outputing the whole '99 bottles of beers on the wall' song from 99 to 1, it put out just the verses from 99 to 96 bottles. Is there something wrong with the loops in Brainfuck code or in the interpreter?

Here is my c code:

#include <stdio.h>
#include <stdlib.h>

int loop(char *commands, int indexOfCommand, int mode){
    int sum = 0;
    int movingIndex = indexOfCommand;
    while(sum > -1){
        movingIndex -= mode;
        if(commands[movingIndex] == ']') 
            sum += mode;
        else if(commands[movingIndex]=='[')
            sum -= mode;
    }
    return movingIndex;
}

int main(){
    unsigned char array[30000] = {0}; // all elements are 0
    unsigned char commands[60000] = {0}; // all elements are 0
    int counter = 0;
    int c;

    int loop(char *commands, int indexOfCommand, int mode);

    while((c = getchar()) != EOF){
        commands[counter] = c;
        counter++;
    }   

    int indexOfArray = counter;
    int indexOfCommands = 0;
    int numOfCommands = 0;

    int length = sizeof(commands)/sizeof(commands[0]); // the length of an array

    while (indexOfCommands < length && numOfCommands < 60000){
        switch(commands[indexOfCommands]){
            case '+':
                if(array[indexOfArray]==255){
                    array[indexOfArray]=0;
                } else array[indexOfArray]++;
            break;
            case '-':
                if(array[indexOfArray]==0){
                    array[indexOfArray]=255;
                }else array[indexOfArray]--;
            break;
            case '>':
                indexOfArray++;
            break;
            case '<':
                indexOfArray--;
            break;
            case '.':
                putchar(array[indexOfArray]);
            break;
            case ']':
                if(array[indexOfArray]!=0) {
                    indexOfCommands=loop(commands,indexOfCommands,1);
                }
            break;
            case '[':
                if(array[indexOfArray]==0){
                    indexOfCommands=loop(commands,indexOfCommands,-1);
                }
            break;
            default:
                // if there is any other character, just ignore it
                break;
        }
        indexOfCommands++;
        numOfCommands++;
    }

    return 0;
}
like image 368
lol Avatar asked May 08 '15 16:05

lol


1 Answers

The condition for premature end of the program execution is here:

while (indexOfCommands < length && numOfCommands < 60000) {
                                   ^^^^^^^^^^^^^^^^^^^^^
    // interpret BF opcodes

    numOfCommands++;
}

You have underestimated how many instruction BF needs to do simple things. (I'm not sure why that condition is in there. Remove it and you'll see all 99 verses.)

like image 155
M Oehm Avatar answered Oct 06 '22 15:10

M Oehm