Contents

Prologue

Brainfuck is a so-called esoteric programming language, meaning it's
"intentionally unusual" (Chris Pressey). Brainfuck was invented by Urban
Müller, whose goal was to create the smallest possible compiler. The second
version of this compiler was 240 bytes in size (compiled ASM)!
Urban Müller also wrote an interpreter in C:

A few years later, an even smaller compiler was made by Raiter, but this time
in binary form. It was 171 bytes in size and ran under Linux. There was a
compiler for DOS as well, which was 136 bytes in size!

While brainfuck is a very restrictive language (only 8 operators can be used,
no variable names, etc.), it's still Turing Complete, i.e. any computational
task can be performed.

The operators

Brainfuck only has 8 operators that are all written as a single character, but
despite its restrictiveness, any program that can be written in pure C can be
written in brainfuck too.

Data, pointers & bytes

To store and read data, an array of 30,000 bytes is used. This array is like an
array of cells, where each cell represents a byte:

[0] [3] [1] [24] [123] [2] [1] [5] [3] [8]
^

Above are the first 10 bytes, the pointer points to byte 2.
Initially, all bytes are set to 0 and the pointer points to the first byte:

[0] [0] [0] [0] [0] [0] [0] [0] [0] [0]
^

From now on, I'll refer to bytes as pn (pointer-n) and to its value
as vn (value-n). So when I write p2v5 I mean that the pointer points to byte
2 and that byte 2 has a value of 5:

[ ] [5] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
^

The values of the other bytes are not displayed, because they aren't known,
I only mentioned p2v5, so other values are unknown.
For further notations, see LEGEND OF NOTATIONS (below).
Since the array consists of bytes, the maximum value a pointer can have is
255. If p1v255 is increased by 1 it'll become p1v0. Likewise, if p1v0 is
decreased by 1 it'll become p1v255.

Legend of notations

p3

pointer 3, value unknown

v25

last mentioned pointer has value 25

p2v5

pointer 2 has a value of 5

p1v/3

pointer 1's value is increased by 3

p5v\2

pointer 5's value is decreased by 2

p8v!0

pointer 8 has a non-zero value

p6v!13

pointer 6 has a value that is not 13

Instead of + and -, / and \ are used, since +'s and -'s shouldn't be used in
comments (the interpreter will not ignore them!) This notation is useful when
a byte's value is unknown, but its value is changed anyway.

Brainfuck interpreter

Before you start programming, you should make sure you have a brainfuck
Interpreter. A brainfuck Interpreter executes your code and takes care of
input and output. My interpreter can be downloaded from the previous page,
or you can write your own!

N.B.: brainfuck source code can contain non-brainfuck characters like
;(*:=1!@#$ since the interpreter will just ignore them. Therefore, my
examples can be copied to the interpreter with comments.
However, some people have added their own operators to the original
brainfuck language, like # (statusdump IIRC). My interpreter will ignore
these characters, but some other interpreters might not!

Your first steps

Let's start with the following program ("Hello World" will come later):

, ;reads character from standard input to byte
under pointer
. ;print byte under pointer to screen

Now let's start manipulating the input:

, ;read character
+ ;increase byte
. ;print byte

So, if input was 'e', then the output will be 'f'.
Next, let's change a lowercase letter to an uppercase letter:

The ASCII value of a lowercase letter is always 32 higher than its matching
uppercase letter, so to print an uppercase letter, the value read from input
has to be decreased by 32.
Next two letters are read, one is stored in p1 and the other in p2:

First, p1v4. When the loop is entered, p2v/3, and p1v\1. This pattern
is repeated until p1v0, so the loop is gone through four times. p2 is
increased by 3 4 times, so eventually p2v12. Voilà, you've multiplied
4 and 3.

And finally, the moment you've all been waiting for, "Hello World!"
This one requires a little introduction though. In brainfuck, output
is given as text, and not as a number (value):

I hope you now understand why "Hello World" shouldn't be your first brainfuck
program, it's way too difficult.

Dividing

You already know how to add, subtract and multiply, so dividing remains. The
following program divides 15 by 3:

+++++++++++++++ ;p1v15
[ ;loop
>+<--- ;p2v/1 p1v\3
] ;end of loop

During every loop 3 gets subtracted from 15, and eventually p1v0. The answer
(15/3=5) is stored in p2.

There is however one problem regarding division: the result must be an
integer, i.e. not a fraction. Here is why: if you would try to divide 15 by 6,
then during every loop 6 would be subtracted from 15, resulting in 15, 9, 3,
-3=253! The result will never be 0, so the program will get stuck in an
infinite loop. Notice that this is not a limitation of brainfuck as a language,
but of this particular method in general.

Moving & copying

Say, p1v5. The loop will be executed five times, p2v5, and p1v0.
You can also use this construction to multiply a byte with a fixed amount:

[ ;loop
>+++<- ;p2v/3 p1v\1
]

Say, p1v5. The loop will be executed five times, and p2v15.
But if you want p1 to be multiplied to itself, you'll have to move p2 to p1
afterwards.

N.B.: Make sure that p2v0 so that p2 will indeed get the value you want it to
get. If p2 already has a non-zero value then something like this might happen:

>+++< ;p2v3 p1
+++++ ;p1v5
[
>+++<- ;p2v/3 p1v\1
]

Instead of p2v15, p2v18 will apply, which is not 3 * 5.
To prevent this, you should empty the byte first:

> ;p2
[ ;loop
- ;execute loop until byte is empty
] ;exit loop

Or, in short, [-]

Copying is almost like moving, but to copy p1 to p2, an extra byte is needed
as workspace. First, p1 is moved to p3, where p3 is the workspace:

[>>+<<-] ;move p1 to p3

Now p3 is moved to p2 and p1:

>> ;p3
[
<+ ;p2v/1
<+ ;p1v/1
>> ;p3
- ;p3v\1
]

Voilà, p1 is copied to p2, and p3 is emptied.

N.B.: always make sure that at the beginning of a loop the pointer points to
the same byte as at the end, because after reaching ']' the interpreter will
return to the matching '[', and the loop might be executed again. The pointer
should then point to the same byte as at the start of the previous loop.
(Notice that this is a beginner's rule of thumb, when you're an advanced
brainfuck-programmer, you might want to ignore this rule (and you should
too ;).)

Next is a program that reads two numbers from keyboard and multiplies them:

If then

A programming language is nothing without IF-THEN-constructions. Luckily,
IF-THEN-constructions can be made in brainfuck, using [ and ].
A [ ]-loop is only entered _IF_ the value under pointer has a non-zero value:

Say, p1v3, the loop is entered and 'H' (value 48h=72d) is displayed.
But if p1v0, the loop will not be entered and nothing is displayed, so only
IF p1 has a non-zero value the loop gets executed.

N.B.: p1v0 after the loop, so if you want to use the value again, you should
have backed it up (by copying) in another byte.

It's nice to be able to display something if a byte is not 0, but it would
be even nicer to display something if a byte has a certain value, including 0!
To do this, first, the value of the byte has to be reduced by number you want
to compare it with. Let's test p1 to see if its value is 64:

If p1 was v64, then now p1v0. If you program a loop that displays something
right now, it would only be entered if p1v!0, but you want the exact opposite.
Therefore, a so-called NOT-port can be used, and p2 is a temporary byte.
Change p2 to p2v1:

>[-]+< ;p2v1 p1

Next you program a loop that does nothing more than empty p2, but only if
p1v!0:

If the input was an '@' (value 40h=64d), an '@' will be displayed, otherwise
a 'N' (Not) will be displayed.

Logical ports

Although there are twelve (some might argue twenty, whatever logical ports),
only AND, OR, XOR and NOT will be discussed here.

For those unfamiliar with logical ports, here's a short introduction:
A logical port is an information manipulator. AND, OR and XOR ports receive
two inputs, while a NOT port receives only one input.
The output of a logical port is either 0 or 1, depending on the value(s) of
the input(s). 0 is called 'false', and !0 (non-zero) is called 'true'.

An AND port will only give 1 as output if both input1 AND input2 are true,
i.e. have non-zero values, the output will be 0 in all other cases, e.g.
input1 = true (!0) and input2 = false (0).

An OR port will give 1 as output if input1 OR input2 OR both are true, the
only case in which the output is 0 is when both inputs are 0.
This port is called an Inclusive OR, or just OR.

A XOR port will give 1 as output if input1 or input2 is true, but not if
both are true. The output will be 0 if both inputs are true or both inputs
are non-true.
This port is called an eXclusive OR, or XOR.

A NOT port will give 1 as output if input1 is false, and 0 as output if
input1 is true.

Of course, you can also combine these ports to create ports such as IN1 AND
NOT(IN2), or IN1 NAND IN2.

Signatures

If you're all crazy about brainfuck or just like it really much, you can try
to make your own sig that has a 'hidden' brainfuck message in it. Below is
mine (try compiling it, but don't feel offended :)

Just something extra

As something extra, I'll show you one of the most difficult brainfuck
programs I've written so far. This program displays whether your input is
even or odd. Say, input is '@' (value 40h=64d), then the output will be '@'s
value is even.'