Inspired a bit by a previous Brainfuck question and the recent fizzbuzz invasion, I decided to make FizzBuzz in Brainfuck.
The code is entirely my own, except for the inclusion of the Printing a number algorithm that I found on StackOverflow.
My code is divided into several parts.
- Setup Construct the tape to contain some data
- Loop through all FizzBuzzes
- Print number if no FizzBuzz was found and Print new line
It was quite a challenge to do this, I started playing around with the basic Brainfuck operators to create the basic tools that I could use. After figuring out how to "search" for a value on the tape, copying/moving a value to another location, and some other useful things, I decided to go with this approach.
The Tape
After the setup section, this is what my tape looks like:
From top to bottom this represent:
- 100 = The number of times to loop
- 10 = New Line character
- 255 = Marker to find the start
- 0 = Counter, what number we're currently at.
- 0 = Boolean to indicate if a FizzBuzz has been found or not (to know if we should print the number)
- Empty space for converting number to string algorithm
Then there is a configurable sequence of:
- 254 = Marker for a FizzBuzz section
- 0 = How many iterations it has been since last print
- 3 / 5 = How many iterations until we will print this text
- Text
- Empty space to indicate end of text
And finally:
- 254 = Marker for a FizzBuzz section
- 253 = End of FizzBuzz sequences
The Approach in regular code
The code does not do a "classic" modulo operation each iteration, instead it can be considered as doing something like this:
int fizz = 3;
int fizzUp = 0;
int buzz = 5;
int buzzUp = 0;
boolean printed = false;
for (int i = 1; i <= 100; i++) {
printed = false;
fizz--;
fizzUp++;
if (fizz == 0) {
print("Fizz");
printed = true;
while (fizzUp > 0) {
fizzUp--;
fizz++;
}
}
// Same for buzz as for fizz
if (!printed) {
print(i);
}
print("\n");
}
Main questions
- Is my Brainfuck code somewhat readable? (I know, I know, it is Brainfuck...) I have tried to add plenty of comments describing what the code does (for once I actually think the what is more important than the why).
- Did I make a good decision to structure the tape in this way?
- Can the setup of the "Fizz" and "Buzz" texts be more efficient?
- Can something else be done more efficient?
- Any other comments appreciated
++++++++++[>++++++++++<-]> Initialize 100 (number of times to perform FizzBuzz)
TAPE MEANINGS
255 Start
254 A Fizz or Buzz text to print
253 End of Fizzes and Buzzes
252 Currently processed FizzBuzz calculation
TAPE OVERVIEW
Remaining Iterations
10 for Line Break
255 Start Marker
Counter
Boolean 1 or 0 for whether or not a fizzbuzz matches current counter
Some empty space for converting counter to string
Any Number of Sequences of the following
254 Indicator for FizzBuzz sequence
Counter
Countdown until next text output
Text any number of characters
Zero
Zero
254 and 253 marker to indicate the end of sequences
>++++++++++ Line break
>- Start marker
>>>>>>>>>>>>>>>> Empty space for counter to string conversion
SETUP Create the Fizz and Buzz sequences on the tape
FIZZ
--> Create indicator
+++++++[->++++++++++<]> Create F
[->+>+>+>+<<<<] Copy 4x F
+++ Set modulo operator to 3
>>+++>>> Adjust second letter to I
++++++++[-<++++<++++<++++>>>] Make the last three lowercase to Fiff
+++++[-<++++<++++>>] Modify the last two F to Z by adding 20
>> Leave two zeros at the end
BUZZ
--> Create indicator
++++++[->+++++++++++<]> Create B
[->+>+>+>+<<<<] Copy 4x B
+++++ Set modulo operator to 5
>>+>++++++>++++++> Adjust BBBB to BCHH
++++++++[-<++++<++++<++++>>>] Make lower case
++++++[-<+++<+++<+++>>>] Adjust Bchh to Buzz
>> Leave two zeros at the end
-->--- Mark the ending with 254 and 253
END OF SETUP
ALGORITHM START
+[-<+]- Go backwards to the 255 mark
<
[
+[->+]- Go forward to the start position 255 marker
<<->> Decrease countdown
>+ Increase counter
>[-] Reset boolean for if we have found a match or not
++[-->++]--> Find next 254 and go one step beyond it
Loop through all 254s
+++[--- Make sure that we are not at 253 (end)
++[--<++]-- Find last value 254
-- Change marker to 252 to indicate that we're processing it
>> Go to the countdown
-< Decrease fizzbuzz countdown
+> Increase fizzbuzz counter
If current marker is NOT zero
[
++++[----<++++]-- Find value 252 and change to 254
[>] Position to a place that is zero to avoid repeat
++[-->++]-- < Find NEXT 254 marker and stop right before it
]
>++
Check if we are positioned on a 254 already then if skip this
[--
We have a match so find start position and mark match
+[-<+]- >> Find 255 marker and go to the boolean
[-]+ Set boolean to 1 whatever the previous value is
++++[---->++++]-- Find value 252 and change to 254
>[->+<] Reset the current FizzBuzz countdown
>>[.>] Print the text
++[-->++] Go to next 254 change to 256 to break loop
]
-->
+++ # Detect if we are at the 253 end
]
---
ALL FIZZBUZZES PROCESSED
Use the boolean to check whether or not to print the number
+[-<+]- Go back to the 255 marker
>> Go to boolean
-[ If boolean is zero then print the number
+>>>
+[-<+]- Go back to the 255 marker
>> We are positioned after the counter
Code taken from StackOverflow below for printing a number
>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-
<+>]>+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->++++++++
<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]
End of StackOverflow code
+[-<+]->> Locate the 255 marker and goto the boolean
]+
Boolean is always one here so print new line
[-]<<<.>>> Print new line
+[-<+]- Go back to the 255 marker
<< Go to the countdown to find out if we should go another round
]
Compressed typical Brainfuckish-version of the code:
++++++++++[>++++++++++<-]>>++++++++++>->>>>>>>>>>>>>>>>-->+++++++[->++
++++++++<]>[->+>+>+>+<<<<]+++>>+++>>>++++++++[-<++++<++++<++++>>>]++++
+[-<++++<++++>>]>>-->++++++[->+++++++++++<]>[->+>+>+>+<<<<]+++++>>+>++
++++>++++++>++++++++[-<++++<++++<++++>>>]++++++[-<+++<+++<+++>>>]>>-->
---+[-<+]-<[+[->+]-<<->>>+>[-]++[-->++]-->+++[---++[--<++]---->>-<+>[+
+++[----<++++]--[>]++[-->++]--<]>++[--+[-<+]->>[-]+++++[---->++++]-->[
->+<]>>[.>]++[-->++]]-->+++]---+[-<+]->>-[+>>>+[-<+]->>>++++++++++<<[-
>+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>
+>>]<<<<<]>[-]>>[>++++++[-<++++++++>]<.<<+>+>[-]]<[<[->-<]++++++[->+++
+++++<]>.[-]]<<++++++[-<++++++++>]<.[-]<<[-<+>]+[-<+]->>]+[-]<<<.>>>+[
-<+]-<<]