TransWikia.com

BF welcomes Fibonnaci

Code Review Asked by Simon Forsberg on January 2, 2022

Slightly inspired by a previous question/april fools joke I decided to take on Fibonnaci sequence in the lovely language Brainfuck.

In order to do this I have also worked on Brainduck, which is a Brainfuck tool/analyzer/IDE. In Brainduck I added the functionality to run Groovy code if the line begins with $.
I wanted this to serve as both a way to make assertions while running the code, to make developing BF programs easier, and to serve as documentation. This question is not primarily about Brainduck though, but about the Brainfuck code I wrote using Brainduck.

A slight summary of the $ stuff I am using:

  • wrapValue, wrapMemory, minValue, maxValue: Sets some settings in Brainduck and also serves as documentation for what the code is compatible with.
  • name: Gives the current memory cell a name which gets displayed in Brainduck
  • assert hasName: Asserts that the current memory cell has the given name. If it doesn’t, Brainduck stops execution of the code.

Primary concerns:

  • Is this readable and understandable? (Yeah yeah, I know it’s BF we’re talking about, but somewhat readable code have been written in BF before)
  • Does my use of the $-lines makes sense? Does it help to understand the code?
  • Can it be even more optimized somehow?

How the code works:

Setup the tape to contain 255 10 0 0 0 1 0 0 0 0 1 0 0 0 49 and print 0 and 1 (the first two Fibonnaci numbers).

  • 255 is for the countdown, how many numbers to print. (Could easily be extended to print more numbers, using something similar to what I wrote in an old answer, such as using 128+128, which could also be 128*128).
  • 10 is, as we all know, the linefeed character.
  • Three zeros for some empty space.
  • A series of digits, first we initialize one digit to contain a 1. Each digit section contains:
    • 0 or 1 to indicate if the digit is being used (The longer the code runs, the more digits will be used)
    • A B and C fields, two of each (explained below) and an overflow field between B and C. Two temp fields and the digit as the ASCII value (48 to 57).

Start looping. For each enabled digit do the following:

  • Initialize 10 at the ’10 minus C’ field
  • Clear B and move A to A2 and B
  • Set A = C
  • Set C = A + B and while doing so check for overflow. If overflow occurs (10 minus C equals zero) then mark the overflow field with 1 and reset the digit to 0 (to simulate “10”)
  • After the addition, check if the overflow field is set. If it is, add 1 to the next digit and activate the next digit if it wasn’t already activated.
  • Move back the A’s B’s and C’s

After all digits has been processed, print them in the order they should appear (higher valued digits are put later in the tape, so loop the tape backwards and print the digits).

Code:

$ wrapValue CRASH
$ wrapMemory CRASH
$ minValue 0
$ maxValue 255

$ name 'countdown'
>
 +++++ +++++ 100
 +++++ +++++ 200
 +++++ 250
 [- < +++++ +++++ >] <
 +++++ 255
> +++++ +++++ Line break
$ name 'lineBreak'

Write out the first ones
>+++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++.<.>+.<.>[-]
$ name 'zero'

>
>
>+
$ name 'digitStart'
Digit 1 Value A
> >
Digit 1 Value B
> >
Digit 1 Value C
>+
>
>
>
>+++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ ++++
$ name 'digit'
<<<<<
<<<<< <<<<

Memory
Countdown or loop condition
New line
Two empty cells

Series of DIGITS:
0 or 1 for if digit is activated
A
A
B
B
C
10 minus C
temp
temp2
digit as char
Empty
Empty



go to start
while (has more digits) {
3   b = a
5   a = c
8   c = a plus b
   if c exceeds 10 during addition then activate next digit and increase it by 1
}


Use countdown
[
$ assert hasName('countdown')
->>>>>
[ For each activated digit
$ assert hasName('digitStart')
    >>> >>>[-]+++++ +++++
    $ name '10minusC'
    <<<
    $ name 'B'
    [-] Clear B
    <    < [->+>+<<] at A after B = A
    $ name 'A'
    >>>>[->>>>-<<<< <<<<+>>>>] Set A = C and stop at C
    $ name 'C'

    Now do C = A plus B
    <
    $ name 'overflow'
<<
    $ name 'A_2'


     customRun('31')
    [
$ assert hasName('A_2')
->>>+>-
>+<[>-]>[<
code2 <<   +>> +++++ +++++
>->]<<
      <<<<] C = B
    <


    [
$ assert hasName('A')
->+>>>+>- Move 1 from A to the current C value  

>+<[>-]>[<
code2 <<   +>> +++++ +++++
>->]<<
      <<<<<]

    >>>
    $ assert hasName('overflow')
    [
        increase next digit and activate it if it wasn't activated already
        >>>>>>>

        Check if next digit was not previously activated

        $ name 'activatedTemp'
          +
        $ name 'activatedTemp2'
          >[<-]<[>
            Activate Digit
            >>> >>> +++++ +++++
            >>> +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++++ +++
            $ name 'digit'
            <<<
            <<< <<<
            End Activate digit
        <-<]>>
        End check if next digit was not previously activated
        $ name 'digitStart'
        [-]+ > +
        <<<< <<
        End increase next digit
        <<----- ----- <-
    ] C plus equals A
    $ assert hasName('overflow')
    <<
    [-<+>] Move right of A back to A

    Move C to number
    >>> [->>+>>+<<<<] >> [-<<+>>]

Goto next activated digits
>>>>>

] End of all activated digits

Print numbers
<<<

Go back and print numbers
[
$ assert hasName('digit')
. <<<<< <<<< <<<]

Print new line
<.

No more numbers to print now go to the counter
<
]
$ assert hasName('countdown')  

If you want to run this code I’d recommend running it with latest released version of Brainduck. Here’s a screenshot of running it in Brainduck:

Fibonnaci code running in Brainduck

Also, a minified typical BF-version of the code:

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

One Answer

EDIT: Takes 10 minutes to learn BF -- and I didn't realize it was so simple.

  1. Is this readable and understandable?
  2. Does my use of the $-lines makes sense?
  3. Does it help to understand the code?
  4. Can it be even more optimized somehow?

Your assert messages are a little strange for me, but I poke fun at how the Spring Framework checks it's own private values to be null and throwing an exception if they are (for the user to handle).

The 100, 200, and 250 could easily be read to 10, 20, 25 and multiply by 10 on the countdown loop.

Write out the first ones but then having the $name 'zero' is unclear because you're on 48/49 -- it's unclear which 'zero' you're referring to. Because you're already printed out (yes your pointer is on zero again but I see a one).

0
1

Digit 1 Value X is fine and it's easy enough to scale. Though I would use "One's place for value X" instead.

The extra increments before and after `$name 'digitStart' are also "what did he do here, and why?"

After taking the time to read how BF works, the "Set A = C and stop at C" is still confusing.

I would also move your Groovy declarations to before the assignment instead of after

$ name 'X'
> +

for example. As a reader that goes line by line, seeing B = A before A has been declared to be something is weird.

Your actual printing out and calculation loop is clever. I was trying to find how you tested if the value got above 9 for the longest time.

Leaving this even though it's completely unneeded and unrelated at this point in case someone wants it. Just for ridiculous reference, this is the one's place repeating sequence. (Length of 60)

0, 1, 1, 2, 3, 5, 8, 3, 1, 4, 5, 9, 4, 3, 7, 0, 7, 7, 4, 1, 5, 6, 1, 7, 8, 5, 3, 8, 1, 9, 0, 9, 9, 8, 7, 5, 2, 7, 9, 6, 5, 1, 6, 7, 3, 0, 3, 3, 6, 9, 5, 4, 9, 3, 2, 5, 7, 2, 9, 1

Answered by David Fisher on January 2, 2022

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP