article sur le Brainfuck, Explication sur le Brainfuck

Brainfuck Article, Signification, Explication

              

Brainfuck est un langage de programmation minimaliste, inventé par Urban Müller en 1993. Le nom est anglais, il vient de la contraction de brain, cerveau, et fuck, niquer. Il a d'ailleurs d'autres noms comme Brainf*ck, Brainf*** ou encore BF. Auraient-ils honte ?

L'objectif de Müller était de créer un langage de programmation simple pour une machine de Turing qu'il pourrait implémenter avec le compilateur le plus petit possible. Le langage consiste en 8 instructions. La version 2 de son compilateur original, écrit pour l'Amiga, faisait 240 octets en taille.

Comme son nom ne le suggère pas pour un anglophobe, les programmes Brainfuck sont difficiles à comprendre, peut-être même dangereux pour la santé mentale des programmeurs. Le Brainfuck est un langage Turing-complet. Ce qui signifie que, malgré les apparences, il est théoriquement possible d'écrire n'importe quel programme informatique en Brainfuck.

Le langage est basé sur un modèle de machine simple consistant en un tableau d'octets initialisés à 0, d'un pointeur sur le tableau (pointant sur le premier octet du tableau) et de 2 files d'octets pour les entrées et les sorties.

Les 8 instructions du langage, chacune codée par une lettre, sont les suivantes :

Caract. Signification

> incrémente (augmente de 1) le pointeur.

< décrémente (diminue de 1) le pointeur.

+ incrémente l'octet du tableau pointé par le pointeur (l'octet pointé).

- décrémente l'octet pointé.
. sortie de l'octet pointé (valeur ASCII).

, entrée d'un octet dans le tableau à l'endroit du pointeur (valeur ASCII).

[ saute à l'instruction après le ] correspondant si l'octet pointé est à 0.

] retourne à l'instruction après le [ si l'octet pointé est différent de 0.

(Alternativement, ] peut être défini par « retourne au [ correspondant ». C'est plus court, mais moins symétrique et moins efficace en temps. Les deux versions produisent des programmes avec le même comportement.)

(Une troisième version équivalente, quoique moins considérée, est : [ signifie « saute après l'instruction ] correspondante », et ] signifie « retourne à l'instruction après le [ correspondant si l'octet pointé est différent de 0 ».)

Les programmes Brainfuck peuvent être traduits en C en utilisant les substitutions suivantes, en considérant que ptr est du type char*:

Brainfuck C

> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr = getchar();
[ while (*ptr) {
] }

Table of contents
1 Exemples
2 Commentaire
3

Exemples

Hello World!

Un programme qui affiche « Hello World! » sur l'écran est :

++++++++++[>+++++++>++++++++++>+++>+<<<<-] >++.>+.+++++++..+++.>++.<<+++++++++++++++. >.+++.------.--------.>+.>.

Brainfuck est intéressant dans ce cas, un programme « Hello World! » n'est pas facile à écrire ! Et à lire !

Remise à zéro de l'octet pointé

[-]

Tant que l'octet est différent de 0, on le décrémente. On arrête donc la boucle ([]) quand il est à 0.

Entrée/Sortie d'un caractère

,.

Prend un caractère du clavier pour l'afficher à l'écran.

Boucle simple

,[.,]

Une boucle qui prend une entrée du clavier et l'affiche à l'écran. Notez qu'on s'attend à avoir un 0 pour marquer la fin de l'entrée (les implémentations peuvent être différentes à ce niveau là).

Manipulation de pointeur

>,[.>,]

Une version améliorée de la boucle précédente dans laquelle on stocke les caractères entrés dans le tableau pour une future utilisation, en déplaçant le pointeur à chaque fois.

Addition

Ce code ajoute l'octet courant (en le détruisant, il sera à 0 à la fin) à l'octet suivant.

[->+<]

Soit Tableau[0] = 2 et Tableau[1] = 8, « [ » débute la boucle, « - » et Tableau[0] = 1, « > » on pointe sur l'octet 1, « + » et Tableau[1] = 9, « ] » on recommence. À la fin, on aura bien Tableau[0] = 0 ce qui arrête la boucle, et Tableau[1] = 10.

Instructions conditionnelles

,----------[----------------------.,----------]

Ce programme prend un caractère minuscule en entrée et le met en majuscule. Pour arrêter, on tape la touche entrée (code 10 en Brainfuck dans la plupart des compilos).

Au début, on récupère le premier caractère (,) et on lui soustrait immédiatement 10 (10 fois -). Si l'utilisateur a tapé entrée, on a 0 dans l'octet pointé et l'instruction de boucle ([) sautera à la fin du programme. Si le caractère entré n'est pas 10, on assume qu'il est en minuscule et on entre dans la boucle, où on va lui soustraire le nombre 22 (22 fois -), ce qui va faire 32 en tout, et 32 est la différence en ASCII entre la lettre minuscule et la même lettre en majuscule.

On va donc l'afficher, puis on en récupère une nouvelle, et à nouveau on lui soustrait 10. Et on repart au début de la boucle. Si le caractère entrée est un Entrée (10), la boucle s'arrêtera comme on l'a déjà vu, sinon on continue.

Addition

,>++++++[<-------->-],,[<+>-],<.>.

Ce programme additionne 2 nombres à un seul chiffre et affiche le résultat si celui-ci n'a aussi qu'un seul chiffre :

4+3

7

(Maintenant les choses vont être un peu plus compliquées. Nous allons nous référer aux octets du tableau ainsi : [0], [1], [2], etc.)

Le premier nombre est entré dans [0], et on lui soustrait 48 pour avoir sa valeur décimale (les codes ASCII pour les chiffres 0-9 sont 48-57). Cela est fait en mettant 6 dans [1] et en utilisant une boucle pour soustraire 8 de [0] autant de fois que dans [1], soit 6 x 48 = 48. C'est une méthode plus commode pour ajouter ou soustraire des grands nombres que de mettre 48 fois « - » dans le programme. Le code qui fait cela est :

>++++++[<-------->-]

>++++++ pour mettre 6 dans [1], puis on attaque la boucle, « < » pour revenir sur [0], on soustrait 8, « > » on repasse sur [1], qu'on décrémente et on retourne dans la boucle. On va bien l'exécuter 6 fois, jusqu'à ce que [1] soit à 0.

Ensuite, on récupère le signe plus qu'on met dans [1] ; puis le second chiffre qui va écraser le signe plus.

La boucle suivante [<+>-] fait le vrai boulot, ajoutant le second nombre dans le premier et remettant à zéro [1]. À chaque boucle, il ajoute 1 dans [0] et retire 1 de [1]  ainsi [1] va finir par être à 0 tout ce qui a été ajouté à [0] a été retiré de [1]. Ensuite la touche entrée est mise dans [1]. (Note : il n'y a eu aucun contrôle des entrées.)

Puis le pointeur est remis sur [0], qui est affiché ([0] est maintenant a + (b + 48), puisqu'on n'a pas corrigé b ; ce qui est identique à (a + b) + 48, qui est ce que l'on veut), Maintenant, le pointeur est ramené sur [1], qui contient la touche entrée ; que l'on affiche, et le boulot est fait.

Multiplication

,>,,>++++++++[<------<------>>-] <<[>[>+>+<<-]>>[<<+>>-]<<<-] >>>++++++[<++++++++>-],<.>.

Comme le précédent, mais effectue une multiplication, pas une addition.

Le premier nombre est entré dans [0], l'astérisque et le deuxième nombre dans [1] et les 2 nombres sont corrigés en leur soustrayant 48 (notez qu'il n'y a qu'une seule boucle de 8 itérations pour soustraire 6 à chaque itération aux 2 nombres !).

Ensuite on entre dans la boucle de multiplication principale. L'idée de base est qu'à chaque boucle on soustrait 1 de [0] et on ajoute [1] dans le total cumulé gardé en [2] (3 * 2 = 2 + 2 + 2). En particulier : la première boucle cumule [1] dans [2] et [3], tout en remettant [1] à 0. (C'est la manière basique de dupliquer un nombre.) La deuxième boucle remet [3] dans [1], en remettant à 0 [3]. Puis on décrémente [0] et on est à la fin de la boucle principale. À la sortie de cette boucle, [0] contient 0, [1] a encore le 2e nombre, et [2] a le produit des 2 nombres. (Si on veut garder le premier nombre, on peut l'ajouter dans [4] à chaque itération de la boucle principale, puis à la fin de déplacer la valeur de [4] dans [0].)

Exemple : 3 * 2

[0] [1] [2] [3]
3 2 0 0
1re boucle : >[>+>+<<-]

3 1 1 1
3 0 2 2
2e boucle : >>[<<+>>-]

3 1 2 1
3 2 2 0
Fin boucle princ : <<<-]

2 2 2 0
1re boucle : >[>+>+<<-]

2 1 3 1
2 0 4 2
2e boucle : >>[<<+>>-]

2 1 4 1
2 2 4 0
Fin boucle princ : <<<-]

1 2 4 0
1re boucle : >[>+>+<<-]

1 1 5 1
1 0 6 2
2e boucle : >>[<<+>>-]

1 1 6 1
1 2 6 0
Fin boucle princ : <<<-]

0 2 6 0

Ensuite, il ne reste plus qu'à ajouter 48 au produit, récupérer la touche entrée dans [3], et afficher le produit ASCIIé et l'entrée qu'on vient juste de stocker.

Commentaire

On peut noter que comme chaque cellule du tableau est un octet, l'instruction « - » est superflue et peut-être remplacée par 255 « + ». De la même manière, les 30 000 cellules formant un tableau circulaire, « < » peut-être remplacé par 29 999 « > ». Cela réduirait le langage à 6 instructions.

.

C'est un article concernant le Brainfuck. La page contient la signification du Brainfuck , Description et explication au sujet de Brainfuck

recherche quelque chose