How to write if else statements in Brainfuck

10.1k views Asked by At

I have just discovered a programming language, which is called Brainfuck.

My question is how to write an if-else statement in Brainfuck?

Is it done by comparing two cells? If yes, then how do I compare two cells in this program?

Thank you

2

There are 2 answers

4
Sirmyself On BEST ANSWER

You need a [x,1] structure, where x can either be 0 or something else. the shortest way to explain it is to make a loop where you know that the pointer does not end the loop where it started.

let's say those cells are named cell1 and cell2

You do operations that change the value of cell1, and cell2's value does not change.

After manipulating values, make your pointer point cell1 and then you do your alternatives.

[-]> cell1 = 0
[-]+ cell2 = 1
|manipulations that change cell1 value
|goto to cell1
[                          // if cell1 != 0
    [-]>[-]                // both cell1 and cell2 now equal 0 
                              if you want the loop to end and want to prevent the 
                              next loop from starting
    |do something
    |goto cell1            // Make sure you point again to cell1 to exit the loop
]>[                        // else
    |do something else
    |goto cell1            // Make sure you point again to cell1 to exit the loop
]

In this example, I use // to mark the comments and I use | to mark operations. Losing track of the pointer is your worst enemy, so it might help to separate your code and to put some comments.


Now! to end up answering your question : no you don't compare two cells, you do operations that either result 0 or something else and then you check if that cell == 0.

the operations you do CAN compare two cells, but you have to make your own sequence to do so


Here's the Wikipedia page for Brainfuck where you can see a lot of simple and complex algorithm for Brainfuck, and welcome to the community :)

https://esolangs.org/wiki/Brainfuck_algorithms#if_.28x.29_.7B_code1_.7D_else_.7B_code2_.7D

0
Tongyu Lu On

Edit: I messed up the @e location in the last post; it should be 1 by default.


Thanks to @Sirmyself for their answer. However, there is a catch: if you do this

# reimplementation of @Sirmyself's answer, bare
>+
<[
    [-]>-
    # if block
<]>[
    -
    # else block
]

# same as above, address-annotated
@0
>@1 +1
<@0 [
    @0 [-]0  # problem
    >@1 -1
    # if block
<@0 ] >@1 [
    @1 -1
    # else block
@1 ]

then the value at @0 is consumed. What's more, if the interpreter is unoptimized, it will try to decrement the value at @0 one at a time and take a very long time to run.

A better way is to use two additional constants @k, @2k and one additional variable @e, like this: (I'm using @1 @2 @3, respectively)

@0
>@1 [-]0 >@2 [-]+1 >@3 [-]+1
<<<@0 [
    # if block
>>>@3 -1 <<@1 ] >@1|2 [ <@1 ] >>@3 [
    # else block
@3 -1 ] +1

More detailed explanation:

@0  # original value
>@1 [-]0 >@2 [-]+1 >@3 [-]+1   # @1 and @2 are constants; (@3)=1 indicates else
<<<@0 [                        # go in from the original value
    # if block
>>>@3 -1 <<@1 ]                # if executes: (@3)=0; (ptr=@1)==0 no loop
>@1|2                          # @1 into @2 (if); @0 into @1 (else)
[ <@1 ]                        # @2 back to (@1)==0 and exits; restabilize at @1
>>@3 [                         # enter block at else flag
    # else block
@3 -1 ] +1                     # reset else flag; exit

Notice that this preserves the original value and does not risk repeatedly decrementing a value.

Important: the original value @o and the constants @k and @2k must be spaced evenly in memory—that is, address-wise, @k - @o == @2k - @k. This is required for the slide-over-and-back to work.

I came across this Stack Overflow page because I wanted to speed up my if-else, but eventually I still had to think up my own solution.

Bare code for copy-paste: (tho I really recommend address-annotating)

>[-]>[-]+>[-]+
<<<[
    # if block
>>>-<<]>[<]>>[
    # else block
-]+