Article dated 04/12/2023 - Written by Di Muro Francesco
The world of programming today is a world full of concepts, instructions, structures and notions thanks to which the programmer can create an application that is useful for the purpose for which it is designed, tested, revised and finally delivered for use .
The best known and most used programming languages tend to have human-readable instructions, in such a way as to facilitate their use by programmers, defining as generically as possible a set of instructions that can be used within the program itself to describe the execution.
However, there is a small family of programming languages which, like other languages, have their own set of instructions to describe the behavior of a program, they tend not to be so human-readable, which is why they are called "esoteric", or "incomprehensible to most".
There are many esoteric languages in the programming world, but the one I want to talk about in this article is "Brainfuck", in a more extended and elegant definition, "things so complicated or unusual that they exceed the limits of one's understanding".
A bit of history
Brainfuck was born in 1993 by Urban Müller, a Swiss physicist with the aim of creating a simple but at the same time complete programming language for a Turing machine, implementing a compiler as small as possible.
With a set of eight instructions, the language is Turing-equivalent or Turing-complete, allowing the programmer to write a wide variety of programs.
The syntax
As anticipated, Brainfuck programs are written using a set of eight instructions with precise roles, based on the manipulation of a memory area of at least 30,000 cells of 1 Byte each, within which it is possible to represent values from 0 to 255 (2^8 - 1). To move inside the memory buffer a pointer is used, which has as its initial position the first cell on the left (cell 0 or c0). The value of each memory cell can be increased, decreased and printed; moreover, it is possible to save the value entered by the user in a memory cell.
The eight instructions made available by the language are:
> : move the pointer from the current position to the right cell ;
< : move the pointer from the current position to the left cell;
+ : increment the value of the memory cell at the current pointer position by one;
- : decrease the value of the memory cell at the current pointer position by one unit;
. : output of the memory cell value at the current pointer position in ASCII encoding;
, : input of the value in the memory cell at the current position of the pointer in ASCII encoding;
[ : start of the iterative cycle, which is executed as long as the memory cell preceding the position of this symbol is different from 0;
] : end of the iterative cycle, which is executed until the memory cell preceding the position of the symbol [ is different from 0.
Practical example
Suppose we want to print the English alphabet (from A to Z), for a total of 26 letters. To perform this task, we have eight instructions available with which we can move within a buffer of 30,000 memory cells of 1 byte each, within which we can save a number from 0 to 255, and of which, in if there is a graphic representation in the ASCII encoding, this is printed on the screen.
Knowing that in ASCII encoding the letter "A" corresponds to the decimal code 65, as a first task it will be necessary to increment c0 (cell 0) up to the number 65, and to do this it will be necessary to use the only increment instruction made available by language, i.e. the + statement.
Thanks to this instruction, it will be possible to increase the value of c0 up to 65, and without the use of further instructions, it would mean writing the + symbol sixty-five times, which is possible but impractical and easy to interpret.
For this reason, it is convenient to use the [ and ] instructions (the iterative loop) to save the number 65, from which the 26 letters of the alphabet can then be printed.
By definition, the iterative cycle of the Brainfuck language is executed until the value of the memory cell preceding the start instruction of the cycle itself is different from 0;
so how can we accomplish this task knowing that it is not possible to define a finite number of iterations directly?
Mathematically, the number 65 is divisible by 1, 5, 13 and itself;
consequently, to use the iterative cycle, it will be necessary to initialize the value of c0 to 5 (65/13), increasing the value of c1 by 13 units at each iteration, using c0 as a counter, which value must be decreased at each iteration so as to reach 0 and pass to the instruction following the end of cycle symbol.
Thanks to this mechanism, after having saved the value 65 in c1, conceptually it will be enough to increase the value by one unit twenty-six times and print the value each time to visualize the alphabet on the screen.
Also for this task, various approaches can be used, but as seen in the previous task, the simplest and most immediate solution is to print and increase the value of c1 by one unit twenty-six times, and to carry out what described, it will be necessary also create iterative cycles.
Since the number 26 does not allow us to increase c1 by one unit twenty-six times with a "cleaner" iterative cycle, the approach used will be to count five times five (for a total of twenty-five iterations), printing the value of c1 and incrementing its value by one with each iteration, then incrementing c1 by one to print the letter Z at the end of the loop.
Consequently, it will be necessary to use cells c2 and c3, within which the value 5 will be initialized, thus using them as counters for two iterative cycles which, in addition to counting up to twenty-five, the nested iterative cycle will print the value of c1 and will increase its value by one unit;
finally, it will be necessary to increase the value of c1 by one unit and print the value to display the letter Z on the screen.
The alphabet program in Brainfuck will therefore be:
Represented in this way, the program is very cryptic, which is why Brainfuck is an esoteric language. Let's see a more descriptive representation of the program:
Below, running the program in a Brainfuck debugger:
Esecuzione del codice
Like (almost) any esoteric language, the purpose of creating and executing a program created precisely with one of these languages, is to think outside the box, to train the mind and add one more argument to one's cultural baggage.