Learn Brainfuck
A beginner-friendly guide to the world's most minimal programming language.
What is Brainfuck?
Brainfuck is a tiny programming language created in 1993 by Urban Müller, a Swiss physics student. His goal was simple: build the smallest possible compiler for a language that could still compute anything. He succeeded, the first compiler was just 296 bytes.
The language has only 8 instructions. That's it. No variables, no functions, no keywords. Despite this, Brainfuck is Turing-complete, meaning it can theoretically compute anything that any other programming language can. It's just... not very practical. And that's the point.
Brainfuck belongs to a family of languages called esoteric programming languages (or "esolangs"), languages designed to be fun, weird, or challenging rather than useful for real work.
The Machine
Before we look at the instructions, you need to understand what a Brainfuck program works with. Think of it like a very simple machine with three parts:
1. The Tape
Imagine a long row of boxes stretching out to the right. Each box holds a single number. When the program starts, every box contains 0. There are 30,000 boxes in total (though you'll rarely need more than a handful).
0
0
0
0
0
2. The Pointer
There's an arrow pointing at one of the boxes. It starts at the very first box (cell 0). When we say "the current cell," we mean whichever box the pointer is pointing at right now. You can move the pointer left and right along the tape.
3. The Numbers
Each cell holds a number from 0 to 255. That's it, no negative numbers, no huge numbers. If you try to go above 255, it wraps back around to 0. If you try to go below 0, it wraps to 255. Think of it like an odometer rolling over.
The 8 Instructions
Every character in a Brainfuck program that isn't one of these 8 symbols is completely ignored. You can write comments however you like, the program will skip over them.
Add 1 to the current cell. If the cell is at 255, it wraps back to 0.
Subtract 1 from the current cell. If the cell is at 0, it wraps to 255.
Move the pointer one cell to the right.
Move the pointer one cell to the left.
Print the current cell's value as an ASCII character. For example, 72 prints H, 101 prints e.
Read one byte of input and store its value in the current cell.
If the current cell is 0, skip ahead to the instruction after the matching ]. Otherwise, continue into the loop.
If the current cell is not 0, jump back to the matching [. Otherwise, continue past the loop.
Your First Program
Let's start with something small. This program outputs the letter A (ASCII value 65):
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
That's 65 + signs followed by a . to print. The cell starts at 0, we add 1 sixty-five times to get 65,
and then we output it. The ASCII character for 65 is A.
It works, but it's pretty tedious. There's a much better way...
Loops: The Key to Everything
Loops are what make Brainfuck actually usable. They let you repeat instructions without writing them out a thousand times.
How Loops Work
A loop is everything between [ and ]. Here are the rules:
- When the program hits
[, it checks the current cell. - If the cell is 0, the entire loop is skipped.
- If the cell is not 0, the program enters the loop.
- When it hits
], it checks the current cell again. - If the cell is not 0, it jumps back to the
[and runs the loop again. - If the cell is 0, it exits the loop and continues.
In other words, a loop keeps running as long as the current cell is not zero. It works just like a while loop in other languages.
Multiplication with Loops
Instead of pressing + sixty-five times, we can use multiplication. To print A (65), we can compute 13 × 5 = 65:
+++++++++++++ Set cell 0 to 13
[ While cell 0 is not 0:
>+++++ Add 5 to cell 1
<- Go back; subtract 1 from cell 0
] Cell 0 is now 0; cell 1 is 65
>. Move to cell 1; print it (A)
Here's what happens: cell 0 starts at 13. Each time through the loop, we move right, add 5 to cell 1, move back left, and subtract 1 from cell 0. After 13 loops, cell 0 is 0 (so the loop stops) and cell 1 is 13 × 5 = 65.
Remember, any character that isn't one of the 8 instructions is ignored. So the words in the example above are just comments.
ASCII: Numbers to Characters
Brainfuck doesn't know about letters. It only knows numbers. The . instruction takes whatever number
is in the current cell and looks it up in the ASCII table to find the matching character.
Here are some useful ASCII values to remember:
10 = newline32 = space48-57 = digits 0-965-90 = A-Z97-122 = a-z
A common mistake: the , (input) instruction stores the ASCII value of whatever
you type, not the number itself. If you type 2, the cell gets 50 (the ASCII code for the
character '2'), not the number 2. Pressing Enter on an empty input gives you 10 (newline).
Common Patterns
Over the years, Brainfuck programmers have discovered small patterns that act as building blocks. Here are the most important ones:
Clear a Cell
[-]
This keeps subtracting 1 until the cell reaches 0. It works no matter what value the cell starts with (because of wrapping, even 255 eventually reaches 0).
Move a Value
[->+<]
This moves the value from the current cell into the next cell. Each loop iteration subtracts 1 from here and adds 1 over there. When it's done, the original cell is 0 and the next cell has the value. Warning: this destroys the original value.
Copy a Value
[->+>+<<]>>[-<<+>>]
Copying is trickier because reading a cell destroys it. The trick is to move the value into two cells (a target and a temporary), then move the temporary copy back. After this, the original cell is preserved and the next cell holds a copy.
Hello World: Step by Step
Here's how the classic Brainfuck "Hello World" works. The strategy is:
- Use a loop to set up several cells with values close to the ASCII codes we need.
- Fine-tune each cell with a few
+or-adjustments. - Print each character by moving to the right cell and using
.
++++++++++ Set cell 0 to 10 (loop counter)
[ Loop 10 times:
>+++++++ Add 7 to cell 1
>++++++++++ Add 10 to cell 2
>+++ Add 3 to cell 3
>+ Add 1 to cell 4
<<<<- Go back to cell 0; subtract 1
]
After the loop:
Cell 0 = 0
Cell 1 = 70
Cell 2 = 100
Cell 3 = 30
Cell 4 = 10
>++. Cell 1: 70 plus 2 = 72 (H)
>+. Cell 2: 100 plus 1 = 101 (e)
+++++++.. Cell 2: 101 plus 7 = 108 (l; printed twice)
+++. Cell 2: 108 plus 3 = 111 (o)
>++. Cell 3: 30 plus 2 = 32 (space)
<<+++++++++++++++. Cell 1: 72 plus 15 = 87 (W)
>. Cell 2: 111 (o)
+++. Cell 2: 111 minus 3 = 114 (r)
------. Cell 2: 114 minus 6 = 108 (l)
--------. Cell 2: 108 minus 8 = 100 (d)
>+. Cell 3: 32 plus 1 = 33 (!)
>. Cell 4: 10 (newline)
The multiplication loop does the heavy lifting. Instead of pressing + 72 times for 'H',
we compute 10 × 7 = 70 and just add 2. Clever, right?
Nested Loops
Loops can go inside other loops. Each [ matches with its corresponding ].
The interpreter keeps track of which brackets go together, so nesting works exactly like you'd expect.
+++ Cell 0 = 3 (outer counter)
[ Outer loop (runs 3 times):
>+++ Cell 1 = 3 (inner counter; reset each time)
[ Inner loop (runs 3 times):
>+ Add 1 to cell 2
<- Subtract 1 from cell 1
] Inner loop ends when cell 1 = 0
<- Subtract 1 from cell 0
] Outer loop ends when cell 0 = 0
After this runs, cell 2 contains 9 (3 × 3). The inner loop runs 3 times for each of the 3 outer iterations.
Common Mistakes
Losing track of the pointer
After a bunch of > and < moves, it's easy to forget which cell you're on. Draw a diagram on paper, seriously, it helps.
Unmatched brackets
Every [ needs a ]. A single missing bracket and nothing works. Count them carefully, especially with nested loops.
Infinite loops
If nothing inside a loop ever brings the checked cell to 0, the loop runs forever. Make sure something in the loop is decrementing (or incrementing towards a wrap to 0).
Confusing ASCII values with numbers
The character 5 has an ASCII value of 53. The , instruction stores 53, not 5. The . instruction prints a character, not a number.
Forgetting moves are destructive
[->+<] zeros out the source cell. If you need the original value later, use the copy pattern with a temp cell instead.
Leftover values in cells
Cells keep their values. If you reuse a cell expecting it to be 0, use [-] to clear it first.
Try It Yourself
The best way to learn Brainfuck is to experiment. Head over to the interpreter and try writing some programs. Use the Debug button to step through your code one instruction at a time, you'll see exactly what each command does to the memory cells.
Here are some challenges to get you started:
- Print your initials
- Print the numbers 0 through 9 (remember: the characters '0' through '9' are ASCII 48 through 57)
- Read a character with
,and print it back with. - Read a lowercase letter and print it in uppercase (hint: the difference between 'a' and 'A' is 32)
A Bit of History
Urban Müller created Brainfuck in 1993 after being inspired by the FALSE programming language, which had a compiler that fit in 1,024 bytes. He wanted to go smaller. His compiler, written in Motorola 68000 assembly for the Amiga, came in at just 296 bytes. A later version shrunk it to 240 bytes. Brian Raiter later wrote a Linux compiler in only 166 bytes.
Mathematically, Brainfuck (minus the I/O instructions) is a minor variation of a language called P'', created by Italian computer scientist Corrado Böhm in 1964, the first language proven to be Turing-complete without using goto-style jumps.
Today, Brainfuck has inspired hundreds of derivative esolangs- Ook! (written in orangutan sounds), COW (bovine-themed), Brainloller (commands encoded as pixel colors in images), and many more.