1. Bases
Pour comprendre Brainfuck, vous devez imaginer un tableau infini de cellules initialisées par 0
chacune.
...[0][0][0][0][0]...
Lorsque le programme brainfuck démarre, il pointe vers n'importe quelle cellule.
...[0][0][*0*][0][0]...
Si vous déplacez le pointeur vers la droite, >
vous déplacez le pointeur de la cellule X vers la cellule X + 1
...[0][0][0][*0*][0]...
Si vous augmentez la valeur de la cellule, +
vous obtenez:
...[0][0][0][*1*][0]...
Si vous augmentez à nouveau la valeur de la cellule, +
vous obtenez:
...[0][0][0][*2*][0]...
Si vous diminuez la valeur de la cellule, -
vous obtenez:
...[0][0][0][*1*][0]...
Si vous déplacez le pointeur vers la gauche, <
vous déplacez le pointeur de la cellule X vers la cellule X-1
...[0][0][*0*][1][0]...
2. Entrée
Pour lire le caractère, vous utilisez une virgule ,
. Ce qu'il fait est: Lire le caractère de l'entrée standard et écrire son code ASCII décimal dans la cellule réelle.
Jetez un œil à la table ASCII . Par exemple, le code décimal de !
est 33
, tandis que a
est 97
.
Eh bien, imaginons que la mémoire de votre programme BF ressemble à:
...[0][0][*0*][0][0]...
En supposant que l'entrée standard signifie a
, si vous utilisez l' ,
opérateur virgule , ce que fait BF est de lire a
le code ASCII décimal 97
en mémoire:
...[0][0][*97*][0][0]...
Vous voulez généralement penser de cette façon, mais la vérité est un peu plus complexe. La vérité est que BF ne lit pas un caractère mais un octet (quel que soit cet octet). Laissez-moi vous montrer un exemple:
Sous Linux
$ printf ł
imprime:
ł
qui est un caractère polonais spécifique. Ce caractère n'est pas encodé par encodage ASCII. Dans ce cas, il s'agit d'un codage UTF-8, il prenait donc plus d'un octet dans la mémoire de l'ordinateur. Nous pouvons le prouver en effectuant un vidage hexadécimal:
$ printf ł | hd
qui montre:
00000000 c5 82 |..|
Les zéros sont décalés. 82
est le premier et c5
est le deuxième octet représentant ł
(dans l'ordre nous les lirons). |..|
est une représentation graphique qui n'est pas possible dans ce cas.
Eh bien, si vous passez ł
comme entrée à votre programme BF qui lit un octet, la mémoire du programme ressemblera à:
...[0][0][*197*][0][0]...
Pourquoi 197
? Eh bien, la 197
décimale est c5
hexadécimale. Cela vous semble familier? Bien sûr. C'est le premier octet de ł
!
3. Sortie
Pour imprimer le caractère, vous utilisez le point .
Ce qu'il fait est: En supposant que nous traitons la valeur réelle de la cellule comme du code ASCII décimal, imprimez le caractère correspondant sur la sortie standard.
Eh bien, imaginons que la mémoire de votre programme BF ressemble à:
...[0][0][*97*][0][0]...
Si vous utilisez maintenant l'opérateur point (.), Ce que fait BF est d'imprimer:
une
Parce que a
le code décimal en ASCII est 97
.
Par exemple, un programme BF comme celui-ci (97 plus 2 points):
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++ ..
Augmentera la valeur de la cellule pointée jusqu'à 97 et l'imprimera 2 fois.
aa
4. Boucles
Dans BF, la boucle comprend le début [
et la fin de la boucle ]
. Vous pouvez penser que c'est comme en C / C ++ où la condition est la valeur réelle de la cellule.
Jetez un œil au programme BF ci-dessous:
++[]
++
incrémente deux fois la valeur réelle de la cellule:
...[0][0][*2*][0][0]...
Et []
c'est comme while(2) {}
, donc c'est une boucle infinie.
Disons que nous ne voulons pas que cette boucle soit infinie. On peut faire par exemple:
++[-]
Ainsi, chaque fois qu'une boucle boucle, elle décrémente la valeur réelle de la cellule. Une fois que la valeur réelle de la cellule est 0
terminée, la boucle:
...[0][0][*2*][0][0]... loop starts
...[0][0][*1*][0][0]... after first iteration
...[0][0][*0*][0][0]... after second iteration (loop ends)
Considérons encore un autre exemple de boucle finie:
++[>]
Cet exemple montre que nous n'avons pas à terminer la boucle à la cellule sur laquelle la boucle a commencé:
...[0][0][*2*][0][0]... loop starts
...[0][0][2][*0*][0]... after first iteration (loop ends)
Cependant, il est bon de terminer là où nous avons commencé. Pourquoi ? Parce que si la boucle termine une autre cellule qu'elle a commencée, nous ne pouvons pas supposer où sera le pointeur de cellule. Pour être honnête, cette pratique rend le brainfuck moins brainfuck.