OOk

OOk

Brainfuck

Brainfuck est un langage de programmation minimaliste, inventé par Urban Müller en 1993. Il tire son nom de l’union de deux mots anglais, brain (cerveau) et fuck (foutre), allusion transparente à l'expression « masturbation intellectuelle ». Ce vocabulaire peu flatteur lui a d'ailleurs valu d'être écrit sous d'autres orthographes plus prudes, telles que Brainf*ck, Brainf*** ou encore BF.

Sommaire

Présentation du langage

L'objectif de Müller était de créer un langage de programmation simple, destiné à fonctionner sur une machine de Turing, et dont le compilateur aurait la taille la plus réduite possible. Le langage se satisfait en effet de seulement huit instructions. La version 2 du compilateur originel de Müller, écrit pour l'Amiga, ne pesait lui-même que 240 octets, la version actuelle se contentant de 171 octets. Le brainfuck est pourtant un langage Turing-complet[1], ce qui signifie que, malgré les apparences, il est théoriquement possible d'écrire n'importe quel programme informatique en brainfuck.

La contrepartie est que, comme son nom ne le suggère peut-être pas pour un non-anglophone, le langage brainfuck produit des programmes difficiles à comprendre. Il suit un modèle de machine simple, consistant en un tableau d'octets initialisés à 0, d'un pointeur sur le tableau (positionné sur le premier octet du tableau) et de deux files d'octets pour les entrées et sorties.

Instructions

Les huit instructions du langage, chacune codée par un seul caractère, 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 sur lequel est positionné 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 où est positionné le 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 ». La formulation est plus courte, mais moins symétrique et moins efficace en temps. Le choix de l'une ou l'autre de ces deux syntaxes n'influe pas sur le comportement final du programme.)

(Une troisième version équivalente, quoique moins considérée, est : [ signifie « saute à 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 unsigned char* :

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

Exemples

Hello World!

Le programme suivant affiche le traditionnel « Hello World! » et une nouvelle ligne à l'écran :

++++++++++
[                   Boucle initiale qui affecte des valeurs utiles au tableau
   >+++++++>++++++++++>+++>+<<<<-
]
                    à la sortie de la boucle le tableau contient:
>++.                      'H'    = 72  (70  plus 2)
>+.                       'e'    = 101 (100 plus 1)
+++++++.                  'l'    = 108 (101 plus 7)
.                         'l'    = 108
+++.                      'o'    = 111 (108 plus 3)
>++.                      espace = 32  (30  plus 2)
<<+++++++++++++++.        'W'    = 87  (72  plus 15)
>.                        'o'    = 111
+++.                      'r'    = 114 (111 plus  3)
------.                   'l'    = 108 (114 moins 6)
--------.                 'd'    = 100 (108 moins 8)
>+.                       '!'    = 33  (32  plus  1)
>.                        nouvelle ligne = 10

Par souci de lisibilité, le code a été divisé en plusieurs lignes et des commentaires ont été ajoutés. Brainfuck considère comme étant des commentaires tous les caractères sauf +-<>[],.. Le code effectivement compilé peut donc se réduire à la ligne suivante :

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

La première ligne initialise a[0] = 10 par de simples incréments successifs à partir de 0. La boucle des lignes 2 à 4 définit de façon effective les valeurs initiales du tableau : a[1] = 70 (proche de 72, le code ASCII du caractère 'H'), a[2] = 100 (proche de 101 ou 'e'), a[3] = 30 (proche de 32, espace) et a[4] = 10 (nouvelle ligne). La boucle fonctionne en multipliant les valeurs de a[0], 10, par 7, 10, 3, et 1, qu'elle stocke dans les cellules voisines. Quand la boucle s'achève, a[0] vaut zéro. >++. déplace alors le pointeur à a[1], qui contient 70, y ajoute 2 (72 étant le code ASCII de la lettre 'H' majuscule), et l'affiche.

La ligne suivante déplace le pointeur vers a[2] et l'incrémente de 1, le résultat, 101, correspondant à 'e', qui est alors affiché.

'l' étant la septième lettre de l'alphabet après 'e', pour obtenir 'll' il faut ajouter 7 (+++++++) à a[2] et l'afficher deux fois.

'o' est la troisième lettre de l'alphabet après 'l', on incrémente donc a[2] trois fois avant d'afficher le résultat.

Le reste du programme fonctionne selon le même principe. Pour les espaces et les lettres en majuscule, ce sont d'autres cellules du tableau qui sont sélectionnées et incrémentées.

Remise à zéro de l'octet pointé

[-]

L'octet est décrémenté (boucle []) jusqu'à ce que sa valeur ait atteint 0.

Entrée/Sortie d'un caractère

,.

Affiche à l'écran un caractère entré au clavier.

Boucle simple

,[.,]

Boucle affichant les caractères entrés au clavier. La fin de la saisie est ici signalée par un 0 (les implémentations peuvent différer sur ce point).

Manipulation de pointeur

>,[.>,]

Une version améliorée de la boucle précédente, dans laquelle les caractères saisis par l'utilisateur sont stockés dans un tableau en vue d'une utilisation future, en déplaçant le pointeur à chaque fois.

Copie d'un octet

On peut distinguer deux manières de copier le contenu d'un octet dans un autre: en effaçant les données de l'octet initial ou en les conservant. Le premier cas est plus simple, le second requérant une variable intermédiaire.

Pour la copie destructive d'un octet dans l'octet suivant, en supposant que le pointeur est sur l'octet à copier:

>[-]< effacer l'octet suivant et revenir sur l'octet initial (facultatif si on sait que l'octet cible est nul)

[->+<] tant qu'il n'est pas nul, lui enlever 1 et ajouter un à l'octet suivant

Pour une copie conservative d'un octet (pointé au départ) dans l'octet suivant, nous allons utiliser l'octet encore après comme variable temporaire. Encore une fois, la première ligne est facultative si on sait que les deux octets suivant l'octet à copier sont nuls.

>[-]>[-]<< on efface les deux octets suivants l'octet à copier puis on revient sur lui

[>+>+<<-] on incrément les deux octets suivants et on décrémente l'octet à copier jusqu'à ce qu'il soit vide. On a donc réalisé deux copies en le détruisant

>>[-<<+>>] on se place sur la deuxième copie et on la copie destructivement sur le premier octet.

Addition

Ce code ajoute l'octet courant (en le détruisant, il est donc remis à 0) à 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. La touche entrée arrête la saisie (code 10 en Brainfuck dans la plupart des compilateurs).

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

Le caractère est affiché, puis un nouveau caractère est récupéré, et à nouveau on lui soustrait 10. Le programme revient alors au début de la boucle : si la touche qu'a validé l'utilisateur est entrée (10), la boucle s'arrête, sinon elle se poursuit.

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 × 8 = 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. La boucle est alors exécutée 6 fois, jusqu'à ce que [1] soit égal à 0.

Ensuite, on récupère le signe + qu'on met dans [1], puis le second chiffre qui écrase le signe +.

La boucle suivante [<+>-] ajoute effectivement le nombre de la seconde cellule dans la première cellule et remet [1] à zéro. À chaque boucle, il ajoute 1 dans [0] et retire 1 de [1] ; ainsi [1] finit 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). Le pointeur est ensuite déplacé sur [1], qui contient la touche entrée, que l'on affiche. L'exécution est terminée.

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 (note : il n'y a qu'une seule boucle de 8 itérations pour soustraire 6 aux deux nombres à chaque itération !).

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 la plus simple 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] contient encore le deuxième nombre, et [2] contient le produit des 2 nombres (pour garder la valeur, il suffit de l'ajouter dans [4] à chaque itération de la boucle principale, puis 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 en ASCII et l'entrée qui vient juste d'être stockée.

Macro-définition Brainfuck

Les macros-définitions ci-dessous définissent des techniques permettant de retrouver des structures ou des instructions utilisées habituellement en algorithmique ou dans les langages de programmation. Elles facilitent la création de programmes Brainfuck. Il existe des implémentations de Brainfuck acceptant la définition de macros.

Les symboles comme a, b ou s représentent chacun un octet différent dans le tableau mémoire. Le symbole t indique un octet utilisé temporairement pour les besoins de la macro. Le symbole s représente un octet utilisé comme source et d un octet utilisé comme destination.

  • Déplacement du pointeur

La macro to(a) consiste à déplacer le pointeur dans le tableau mémoire au niveau de l'octet a. Elle s'obtient avec une série de < ou de >.

  • Ajout d'une constante

La macro addCst(n) ajoute à l'octet pointé la valeur n. Elle s'obtient avec une série de + ou de - selon le signe de n.

  • Mise à zéro d'un octet
zero(m): to(m) [-]
  • Déplacer un octet
move(s d): to(s) [- to(d)+ to(s)]
  • Déplacer un octet vers deux autres octets
move2(s d1 d2): to(s) [- to(d1)+ to(d2)+ to(s)]
  • Copie d'un octet vers un autre
copy(s d t): move2(s d t) move(t s)
  • Structure conditionnelle simple
if(a)  : to(a) [
endif(a): zero(a) ]
  • Structure conditionnelle avec alternative
ifelse(a t): to(t)+ to(a) [ to(t)-
else(a t)  : zero(a) ] to(t) [
endelse(t) : to(t)- ]
  • Structure répétitive
for(s) : to(s) [
next(s): to(s)- ]
  • Échange de deux octets
swap(a b t): move(a t) move(b a) move(t b)

Commentaire

On peut noter que, dans la version initiale, 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 à six instructions.

Cependant, la taille du tableau, la taille des cellules et les possibilités de "wrapping" (i.e. que faire > sur la dernière case ramène à la première ou que + sur un octet plein le met à 0) ne font pas partie des spécifications du langage et sont laissées à la liberté des compilateurs. Ainsi, cette réduction à six instructions n'est pas toujours possible. Quand bien même, il peut nuire à la portabilité de jouer sur le wrapping.

La seule contrainte imposée par le concepteur du langage est au moins 30 000 cellules et au moins un octet par cellule. Certaines implémentations proposent deux, quatre ou huit octets par cellule, voire aucune limitation!

Variantes

Brainfuck a de nombreux descendants. La plupart se contentent de rendre le code encore plus inextricable (par exemple f*ckf*ck, le langage Pi, ou bien Ook! décrit ci-dessous); d'autres ajoutent de réelles fonctionnalités (les langages fm, Nanopond).

Ook!

Le langage Ook est une variante de brainfuck. C'est un langage Turing-complet, conçu pour être parfaitement lisible par un orang-outan, en référence au personnage du bibliothécaire de l'univers du Disque-monde de Terry Pratchett.

Ook Brainfuck Signification
Ook. Ook? > incrémente (augmente de 1) le pointeur.
Ook? Ook. < décrémente (diminue de 1) le pointeur.
Ook. Ook. + incrémente l'octet du tableau sur lequel est positionné le pointeur (l'octet pointé).
Ook! Ook! - décrémente l'octet pointé.
Ook! Ook. . sortie de l'octet pointé (valeur ASCII).
Ook. Ook! , entrée d'un octet dans le tableau à l'endroit où est positionné le pointeur (valeur ASCII).
Ook! Ook? [ saute à l'instruction après le Ook? Ook! correspondant si l'octet pointé est à 0.
Ook? Ook! ] retourne à l'instruction après le Ook! Ook? si l'octet pointé est différent de 0.
Hello world en Ook :

Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook! Ook? Ook! Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook! Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook. Ook? Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook. Ook. Ook? Ook. Ook. Ook! Ook. Ook. Ook? Ook! Ook.

Spoon

Le langage spoon est équivalent au langage brainfuck mais avec des mots constitués de 0 et 1.

Spoon Brainfuck Signification
010 > incrémente (augmente de 1) le pointeur.
011 < décrémente (diminue de 1) le pointeur.
1 + incrémente l'octet du tableau sur lequel est positionné le pointeur (l'octet pointé).
000 - décrémente l'octet pointé.
0010110 . sortie de l'octet pointé (valeur ASCII).
001010 , entrée d'un octet dans le tableau à l'endroit où est positionné le pointeur (valeur ASCII).
00100 [ saute à l'instruction après le 0011 correspondant si l'octet pointé est à 0.
0011 ] retourne à l'instruction après le 00100 si l'octet pointé est différent de 0.

Hello world en spoon

1 1 1 1 1 1 1 1 1 1 00100 010 1 1 1 1 1 1 1 010 1 1 1 1 1 1 1 1 1 1 010 1 1 1 010 1 011 011 011 011 000 0011 010 1 1 001010 010 1 001010 1 1 1 1 1 1 1 001010 001010 1 1 1 001010 010 1 1 001010 011 011 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 001010 010 001010 1 1 1 001010 000 000 000 000 000 000 001010 000 000 000 000 000 000 000 000 001010 010 1 001010 010 001010

Il est à noter que les espaces peuvent être supprimés :

Hello world en spoon (sans espace)

1111111111001000101111111010111111111101011101010110110110110000011010110010100101001010111111100 1010001010111001010010110010100110111111111111111110010100100010101110010100000000000000000000010 100000000000000000000000000010100101001010010001010

Cela fait bien entendu référence a un fichier binaire (exécutable)

Notes et références

Voir aussi

Liens externes

  • Portail de la programmation informatique Portail de la programmation informatique
Ce document provient de « Brainfuck ».

Wikimedia Foundation. 2010.

Contenu soumis à la licence CC-BY-SA. Source : Article OOk de Wikipédia en français (auteurs)

Игры ⚽ Поможем решить контрольную работу

Regardez d'autres dictionnaires:

  • Ook! — ist eine Variante der esoterischen Programmiersprache Brainfuck für Orang Utans, entwickelt von David Morgan Mar.[1] Obwohl bei Ook! der humoristische Ansatz im Vordergrund steht, eignet es sich gut dazu einige Grundlagen zum Design von… …   Deutsch Wikipedia

  • Ook! — (con el signo de exclamación) es un lenguaje de programación esotérico Turing completo. Este lenguaje es una parodia de Brainfuck, del que toma su conjunto completo de comandos (ver tabla). Deriva su completitud Turing de esta relación. Según su… …   Wikipedia Español

  • Ook — or OOK may refer to: Ook Chung (born 1963), a Korean Canadian writer from Quebec OOK, acronym of on off keying OOK, IATA airport code for Toksook Bay Airport, Alaska Ook language (Discworld), one half of the vocabulary of the fictional orangutan… …   Wikipedia

  • Ook! — (con el signo de exclamación) es un lenguaje de programación esotérico Turing completo diseñado para orangutanes. El lenguaje tiene 3 palabras reservadas (Ook., Ook?, y Ook!); que pueden combinarse en ocho maneras diferentes para formar el… …   Enciclopedia Universal

  • Ook — ([=o]k), n. Oak. [Obs.] A branched ook. Chaucer. [1913 Webster] …   The Collaborative International Dictionary of English

  • Ook — Brainfuck Brainfuck est un langage de programmation minimaliste, inventé par Urban Müller en 1993. Il tire son nom de l’union de deux mots anglais, brain (cerveau) et fuck (foutre), allusion transparente à l expression « masturbation… …   Wikipédia en Français

  • Ook! — Brainfuck Brainfuck est un langage de programmation minimaliste, inventé par Urban Müller en 1993. Il tire son nom de l’union de deux mots anglais, brain (cerveau) et fuck (foutre), allusion transparente à l expression « masturbation… …   Wikipédia en Français

  • OOK — Die Abkürzung bzw. das Wort OOK steht für: On Off Keying, eine binäre Modulationsart, die einfachste Form der Amplitudentastung Ook!, eine Variante der esoterischen Programmiersprache Brainfuck …   Deutsch Wikipedia

  • Ook — Die Abkürzung bzw. das Wort OOK steht für: On Off Keying, eine binäre Modulationsart, die einfachste Form der Amplitudentastung Ook!, eine Variante der esoterischen Programmiersprache Brainfuck Diese Seite ist eine Begriffsklärung …   Deutsch Wikipedia

  • ook — interjection The cry of a monkey. He tapped the Librarian on the shoulder. Excuse me mdash; Ook? Those guys just called you a monkey, said Glod …   Wiktionary

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”