15
\$\begingroup\$

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:

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:

>+++++++++++++++++++++++++[-<++++++++++>]<+++++>++++++++++>+++++++++++
+++++++++++++++++++++++++++++++++++++.<.>+.<.>[-]>>>+>>>>>+>>>>+++++++
++++++++++++++++++++++++++++++++++++++++++<<<<<<<<<<<<<<[->>>>>[>>>>>>
[-]++++++++++<<<[-]<<[->+>+<<]>>>>[->>>>-<<<<<<<<+>>>>]<<<[->>>+>->+<[
>-]>[<<<+>>++++++++++>->]<<<<<<]<[->+>>>+>->+<[>-]>[<<<+>>++++++++++>-
>]<<<<<<<]>>>[>>>>>>>+>[<-]<[>>>>>>>++++++++++>>>+++++++++++++++++++++
+++++++++++++++++++++++++++<<<<<<<<<<-<]>>[-]+>+<<<<<<<<----------<-]<
<[-<+>]>>>[->>+>>+<<<<]>>[-<<+>>]>>>>>]<<<[.<<<<<<<<<<<<]<.<]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.