Interpréteur de Brainfuck

En 1993, un étudiant allemand nommé Urban Müller a créé un langage de programmation minimaliste pouvant fonctionner sur une machine de petite capacité. N'utilisant que huit instructions, son créateur lui-même doutait que quiconque puisse programmer quoi que ce soit d'utile avec ce langage...

De part son aspect exotique et sa difficulté d'utilisation, ce langage a été nommé Brainfuck (inutile de traduire...). On en présente ici une version spécifique à CodEx.

Description du langage

Un interpréteur de Brainfuck est une machine constituée des éléments suivants :

  • Une chaîne de caractères pour le programme, qui contient les instructions à exécuter ;
  • Un tableau de mémoire qui permet de stocker des informations et de les modifier au besoin ;
  • Un flux d'entrée, qui permet à l'utilisateur d'entrer des données dynamiques au cours de l'exécution du programme ;
  • Un flux de sortie, qui permet d'afficher le résultat des exécutions.

La mémoire est donc modélisée par un tableau. Dans sa description classique, Brainfuck utilise un tableau de 30 000 cases, mais dans le cadre de cet exercice on limite la taille du tableau à 10 cases.

Les cases du tableau peuvent stocker des nombres entiers codés sur un octet. On considère dans cet exercice que les valeurs sont des nombres positifs entre 0 et 2551. Si jamais une opération a pour résultat une valeur sortant de cet intervalle, on « boucle » sur celui-ci. Ainsi, dans la mémoire, 255 + 1 = 0 et 0 - 3 = 253.

L'interpréteur utilise un pointeur, sous forme d'un nombre entier, lui permettant de conserver l'indice de la case mémoire actuellement utilisée. Initialement ce pointeur désigne la première case du tableau (d'indice 0).

Le programme est une simple chaîne de caractères, chacun d'entre eux correspondant à une instruction. L'interpréteur utilise un compteur lui permettant de garder trace de l'indice dans la chaîne de caractères de l'instruction en cours. Initialement ce compteur désigne la première instruction du programme (d'indice 0). L'exécution s'arrête lorsque ce compteur se retrouve en dehors du programme (et donc lorsque le compteur devient égal à la longueur du programme).

Le langage utilise huit instructions s'écrivant avec les symboles ><+-.,[] et qui sont décrites ci-dessous :

Instruction Rôle
> Ajoute 1 au pointeur. On passe donc à la case de droite dans la mémoire
< Soustrait 1 au pointeur. On passe à la case de gauche dans la mémoire
+ Ajoute 1 à la valeur de la case mémoire pointée actuellement
- Soustrait 1 à la valeur de la case mémoire pointée actuellement
. Ajoute à la sortie le caractère ASCII correspondant à la valeur de la case mémoire pointée actuellement
, Lit un caractère sur le flux d'entrée et stocke son code ASCII dans la case mémoire pointée actuellement
[ Incrémente le compteur jusqu'au prochain crochet fermant correspondant à celui à la position actuelle si la valeur de la case pointée est nulle
] Décrémente le compteur jusqu'au précédent crochet ouvrant correspondant à celui à la position actuelle si la valeur de la case pointée est non nulle

Le flux de sortie est modélisé par une chaîne de caractères qui regroupe l'ensemble des caractères affichés au fil de l'exécution.

Le flux d'entrée sera mis en place à l'aide de la fonction builtin input qui demande à l'utilisateur de taper un caractère durant les exécutions.

La chaîne de caractères "++>---." est donc un exemple de programme Brainfuck. Ce programme incrémente deux fois la première case de la mémoire (elle contient alors la valeur 2), décale le pointeur d'une case à droite, décrémente la valeur de celle-ci trois fois (elle contient la valeur 253) puis affiche le caractère "ý" correspondant à ce code ASCII.

L'ensemble de ces instructions permettent, entre autres choses, de simuler une machine de Turing. Brainfuck est donc turing-complet ce qui signifie qu'il est possible d'y coder tout ce que peut coder Python !

Rôle des crochets: [ et ]

Cette partie n'est pas nécessaire pour réaliser l'exercice, mais elle apporte des éclairages sur le fonctionnement du langage Brainfuck.

On voit ci-dessus que lorsqu'il rencontre une instruction de type crochet dans le programme, le comportement de l'interpréteur dépend de la valeur de la cellule mémoire pointée actuellement. Si cela peut paraître surprenant à première vue, ce comportement est néanmoins très important car il est à la base de nombreuses « constructions » (au sens de syntaxes) qui permettent de recréer des éléments algorithmiques essentiels : conditions (if) et boucles (while) notamment :

  • au moment où le compteur est sur un crochet ouvrant [ :

    • si la cellule mémoire pointée actuellement est non nulle, l'interpréteur va exécuter les instructions entre ce crochet et son fermant correspondant ;
    • sinon, ces instructions ne seront pas exécutées.

    Ceci permet donc de construire un test if cellule != 0: ;

  • dans le cas où le code entre crochets est exécuté, si à l'issue de cette exécution la même cellule mémoire est pointée et qu'elle contient une valeur non nulle, l'interpréteur revient au crochet ouvrant correspondant. Cette construction permet donc de mettre en place une boucle while cellule != 0:.

L'objectif de cet exercice est d'écrire un interpréteur de Brainfuck (et pas d'écrire des programmes dans ce langage 😅). Le site https://brainfuck.net/ permet néanmoins de faire quelques essais.

De façon générale, on garantit que dans toutes les questions :

  • tous les programmes proposés dans les tests sont bien formés :
    • les instructions ne font pas sortir de la mémoire (on ne fera jamais 11 décalages consécutifs sur la droite par exemple) ;
    • les crochets sont cohérents (on ne rencontre pas de cas tels que "[]]") ;
  • les valeurs saisies par l'utilisateur ont toutes des codes ASCII compris entre 0 et 255.

Pour représenter l'état de l'interpréteur on utilise un dictionnaire. Celui-ci contient plusieurs couples {clé: valeur} détaillés ci-dessous :

Clé Valeur à l'initialisation Rôle
"programme" le programme à exécuter Permet de récupérer l'instruction à exécuter
"compteur" 0 Indice de la prochaine instruction à exécuter dans le programme
"mémoire" [0] * 10 Tableau de mémoire
"pointeur" 0 Indice de la case de la mémoire actuellement manipulée
"sortie" "" Chaîne de caractères reprenant l'ensemble des caractères ajoutés à la sortie

On insiste sur le fait que l'on manipule deux indices. Si bf est le dictionnaire décrivant l'état de l'interpréteur :

  • bf["compteur"] est l'indice de l'instruction étudiée dans le programme. Lors de l'exécution, cet indice évolue entre 0 et len(programme) (le plus souvent en passant à l'instruction suivante sauf dans le cas des crochets qui peuvent décaler le compteur vers l'avant ou l'arrière de plus d'une unité). Lorsque la fin du programme est atteinte, si bf["compteur"] == len(programme), l'exécution s'arrête ;

  • bf["pointeur"] est l'indice de la case de la mémoire considérée. Celle-ci comportant toujours 10 cases, bf["pointeur"] prend des valeurs comprises entre 0 et 9 (inclus).

De plus, bf["sortie"] permet de stocker l'ensemble des caractères affichés au fil de l'exécution. Ainsi, si un programme affiche successivement "a" puis "b", bf["sortie"] vaudra "ab" à la fin de l'exécution.

Exemple de dictionnaire

À la fin de l'exécution du programme "++>---.", le dictionnaire bf décrivant l'interpréteur aura les valeurs suivantes :

Etat de l'interpréteur
>>> bf["programme"]
'++>---.'
>>> bf["compteur"]
7
>>> bf["mémoire"]
[2, 253, 0, 0, 0, 0, 0, 0, 0, 0]
>>> bf["pointeur"]
1
>>> bf["sortie"]
'ý'

On pourra remarquer que le "compteur" a pour valeur 7 qui est la longueur du programme. La sortie contient quant à elle le caractère 'ý' dont le code ASCII est 253.

Le codage d'un interpréteur complet nécessitant plusieurs étapes, nous allons découper l'ensemble du programme en plusieurs fonctions.

Mis à part la fonction interpreteur, toutes ces fonctions renvoient le dictionnaire décrivant l'état de l'interpréteur. Ce choix permet de simplifier les test mais n'est pas indispensable. En effet, le dictionnaire d'état passé en paramètre des fonctions est mutable : celles-ci manipulent toutes le même objet et les modifications effectuées par l'une sont toujours visibles par les autres.

Fonction Paramètre Rôle
creation Le programme à exécuter programme Crée le dictionnaire décrivant l'interpréteur
incremente Le dictionnaire décrivant l'interpréteur bf Augmente de 1 la valeur de la case mémoire pointée
decremente Le dictionnaire décrivant l'interpréteur bf Diminue de 1 la valeur de la case mémoire pointée
droite Le dictionnaire décrivant l'interpréteur bf Augmente de 1 la valeur du pointeur
gauche Le dictionnaire décrivant l'interpréteur bf Diminue de 1 la valeur du pointeur
sortie Le dictionnaire décrivant l'interpréteur bf Ajoute le caractère correspondant à la valeur de la case mémoire pointée à la sortie
entree Le dictionnaire décrivant l'interpréteur bf Donne à la case pointée le code ASCII correspondant au caractère saisi par l'utilisateur
fermant_correspondant Le dictionnaire décrivant l'interpréteur bf Incrémente compteur jusqu'à l'instruction "]" correspondante
ouvrant_correspondant Le dictionnaire décrivant l'interpréteur bf Décrémente compteur jusqu'à l'instruction "[" correspondante
interpreteur Le programme à exécuter programme Exécute le programme passé en paramètre

Les questions ci-dessous demandent de coder ces différentes fonctions. Elles sont indépendantes. Seule la dernière question qui demande de coder l'interpréteur complet utilise les fonctions précédentes.

Fonction creation

La fonction creation prend en paramètre un programme à exécuter et renvoie le dictionnaire décrivant l'interpréteur dans son état initial.

Exemple
>>> creation("+")
{'programme': '+', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk02Po, 5}*6]ual84t/sbr[vce3)fh{:1S=é7dp(050S0G0y0u0c0v0A0n0F0v0u0A0A0P010y0c0T010406050A0t0d0d0u0C0g040O0l0v0t0/0l0b050z0_0{0}0 0@0T04181f051i0z1i1k1f0@0S0c0E0%0)0+0-0K0c0f0K0v1y0K0y0=050Y0B0v0G1t0*0,011x1z1B1z0y1H1J1F0y0B0l0S0 1G0C1g0y0K0%120A0T0u0b0-0j011L1v010J0!0G0b0u0d0G1F1-1/1@1N1`1J1}1 0=0a0n0k0C0l0T0l0A0c150b0n0W1+0C0C0G0F2k18220b1g0z1)2x0y1%1$1(0S240-1B0b1|2h1F1q1s0(1M2H0c2J0b1Z1r1F0T2q1g2v2x2#0^1.2l2P1^2U0C0|0v0=0N2u2)0?2(232+1N2-2/0=0j2?1/2^2v2G012}0u2:040H312w0@342{0-37390x3c332)353i0=0o3l3e3n3g360l2.380=0r3s2_2*1u2|3x2~040R3C3f3F3h3H3z040w3l1h2Z182N2A0S2E350F1Z201g3X1j3V2%192@053$0W2!3u3N010h0=0W0J3T3M2Q010e0=0n3~3@400b0J0=0F2q0u2t3.323D350;040U452`3^0b0=2Y0l0f0C1~1 4m3E404j0I0M3s0n4E443 1^3`042q0y0t0C174f2w4G461^4j0L4D4F4Y4h3v0A1=04013$0d0T0y0G4N014x4i0=4C4Q044S4n400d0c0=0i4;3v4j0m4X4Y4E4!3^4$0=014r4t4v20513^4j4@2#4`4y2,4q2e5e0{0G5h4z0=544^06564F58405a4(0d0Q0d0l0c2q4:4^5C4U4?3l5m4=040D5u1^4}4 5W1N4j0s5R5O1N0l0=0q5(4H1N5Y040N505N5/0-5355565)0-5E5c5J0b4-4/5!5`5Q4^5S3v5;5@2%5_5c5w5|4Z6f600A3x0/5g5^4T5#685l5~01605M6e6r67045x2#5z5B6f4j0p3C0z3;0G2x2Y6N3W1r3Y2A2C2y1Y1!2A0u1I6Q0z3X0@6%0X0Z0#04.
Fonction incremente

La fonction incremente prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et incrémente la valeur de la case pointée.

Cette fonction renvoie le dictionnaire modifié.

On rappelle que les valeurs de la mémoire sont des entiers compris entre 0 et 255. Si la valeur obtenue après l'incrémentation dépasse 255, on la remet à 0.

Exemple
>>> bf = {'programme': '+', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> incremente(bf)  # incrémente la case 0
{'programme': '+', 'compteur': 0, 'mémoire': [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nim%wgyk2Po 5+]u6al4t/sbr[vce3)fh:1S=édp(050N0D0v0s0c0t0x0m0C0t0s0x0x0L010v0c0O010406050x0q0d0d0s0z0h040K0l0t0q0*0l0b050w0;0?0^0`0/0O04131a051d0w1d1f1a0/0N0c0B0Y0!0$0(0H0c0g0H0t1t0H0v0-050T0y0t0D1o0#0%011s1u1w1u0v1C1E1A0v0y0l0N0`1B0z1b0v0H0Y0}0x0O0s0b0(0j011G1q010G0V0D0b0s0d0D1A1(1*1/1I1=1E1^1`0-0a0m0k0z0l0O0l0x0c100b0m0R1$0z0z0D0C2f131}0b1b0w1!2s0v1Y1X1Z0N1 0(1w0b1@2c1A1l1n0Z1H2C0c2E0b1U1m1A0O2l1b2q2s2W0:1)2g2K1:2P0z0@0t0-0J2p2!0.2Z1~2$1I2(2*0-0j2.1*2:2q2B012^0s2+040E2|2r0/2 2?0(32340u372~2!303d0-0n3g1c2U132I2v0N2z300C1U1{1b3r1e3p2Y142/053w0R2V3i3b010i0-0R0G3n3a1p1I0f0-0m3R3K3T3c0G0-2N0C2l1`0b0v0D3Y2=3!010,040P3/2#3;0b0-0y3Q3E2}2;3`2L3=0-0F0I3g060m4b3X3S443|042b2N3-0q0z3g4d3Z440l0-0L4n423j3}3 2Y4e1:3?0A3_300x1-043=0l4j0D4l014E3L3?0p494c4o3:4f0-1`0d4K2l4u4A1I4r044t402r4V432%4x4P3;4C4?444G0-010d0M4!0c2l4O4-3J4W4B0-4S544a4c4v3L4g4Z4#3.545d4@0-4D5j4(3c0-4i3,4M4m5o4p5704592W4/304*4,5B5k443?3^5w562@4Y0D504$5L4:1I4^5S4w4h4K5t4l4_5y5A2/5C3L4*0o4%5x1I0d0c2,5$5U465.5M0(4*0e5`5T0(5;2`0n0r4T5c5p3M0-2l0v4l12545*3{4=5a133H0D2s2T6m3q1m3s2v2x2t1T1V2v0s1D6p0w3r0/6C0S0U0W04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nim%wgyk2Po 5+]u6al4t/sbr[vce3)fh:1S=édp(050N0D0v0s0c0t0x0m0C0t0s0x0x0L010v0c0O010406050x0q0d0d0s0z0h040K0l0t0q0*0l0b050w0;0?0^0`0/0O04131a051d0w1d1f1a0/0N0c0B0Y0!0$0(0H0c0g0H0t1t0H0v0-050T0y0t0D1o0#0%011s1u1w1u0v1C1E1A0v0y0l0N0`1B0z1b0v0H0Y0}0x0O0s0b0(0j011G1q010G0V0D0b0s0d0D1A1(1*1/1I1=1E1^1`0-0a0m0k0z0l0O0l0x0c100b0m0R1$0z0z0D0C2f131}0b1b0w1!2s0v1Y1X1Z0N1 0(1w0b1@2c1A1l1n0Z1H2C0c2E0b1U1m1A0O2l1b2q2s2W0:1)2g2K1:2P0z0@0t0-0J2p2!0.2Z1~2$1I2(2*0-0j2.1*2:2q2B012^0s2+040E2|2r0/2 2?0(32340u372~2!303d0-0n3g1c2U132I2v0N2z300C1U1{1b3r1e3p2Y142/053w0R2V3i3b010i0-0R0G3n3a1p1I0f0-0m3R3K3T3c0G0-2N0C2l1`0b0v0D3Y2=3!010,040P3/2#3;0b0-0y3Q3E2}2;3`2L3=0-0F0I3g060m4b3X3S443|042b2N3-0q0z3g4d3Z440l0-0L4n423j3}3 2Y4e1:3?0A3_300x1-043=0l4j0D4l014E3L3?0p494c4o3:4f0-1`0d4K2l4u4A1I4r044t402r4V432%4x4P3;4C4?444G0-010d0M4!0c2l4O4-3J4W4B0-4S544a4c4v3L4g4Z4#3.545d4@0-4D5j4(3c0-4i3,4M4m5o4p5704592W4/304*4,5B5k443?3^5w562@4Y0D504$5L4:1I4^5S4w4h4K5t4l4_5y5A2/5C3L4*0o4%5x1I0d0c2,5$5U465.5M0(4*0e5`5T0(5;2`0n0r4T5c5p3M0-2l0v4l12545*3{4=5a133H0D2s2T6m3q1m3s2v2x2t1T1V2v0s1D6p0w3r0/6C0S0U0W04.
Fonction decremente

La fonction decremente prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et décrémente la valeur de la case pointée.

Cette fonction renvoie le dictionnaire modifié.

Exemple
>>> bf = {'programme': '-', 'compteur': 0, 'mémoire': [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> decremente(bf)  # décrémente la case 0
{'programme': '-', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nim%wgyk2Po 56]ual4t/sbr[vce3)fh-:1S=édp(050N0C0u0r0c0s0w0m0B0s0r0w0w0L010u0c0O010406050w0q0d0d0r0y0h040K0l0s0q0*0l0b050v0;0?0^0`0/0O04131a051d0v1d1f1a0/0N0c0A0Y0!0$0(0G0c0g0G0s1t0G0u0-050T0x0s0C1o0#0%011s1u1w1u0u1C1E1A0u0x0l0N0`1B0y1b0u0G0Y0}0w0O0r0b0(0j011G1q010F0V0C0b0r0d0C1A1(1*1/1I1=1E1^1`0-0a0m0k0y0l0O0l0w0c100b0m0R1$0y0y0C0B2f131}0b1b0v1!2s0u1Y1X1Z0N1 0(1w0b1@2c1A1l1n0Z1H2C0c2E0b1U1m1A0O2l1b2q2s2W0:1)2g2K1:2P0y0@0s0-0J2p2!0.2Z1~2$1I2(2*0-0j2.1*2:2q2B012^0r2+040D2|2r0/2 2?0(32340t372~2!303d0-0n3g1c2U132I2v0N2z300B1U1{1b3r1e3p2Y142/053w0R2V3i3b010i0-0R0F3n3a1p1I0f0-0m3R3K3T3c0F3O2m2l1`0b0u0C3Y2=3!010,040P3.2#3:0b0-0x3Q3E2}2;3_2L3;0-0E0I3g060m4a3X3S433{042b2N3,0q0y3g4c3Z430l0-0L4m413j3|3~2Y4d1:3=0z3^300w1-043;0l4i0C4k014D3L3=0p484b4n3/4e0-1`0d4J2l4t4z1I4q044s3 2r4U422%4w4O3:4B4=434F0-010d0M4Z0c2l4N4,3J4V4A0-4R53494b4u3L4f4Y4!3-535c4?0-4C5i4%3c0-4h3+4L4l5n4o5604582W4.304)4+5A5j433=3@5v552@4X0C4 4#5K4/1I4@5R4v4g4J5s4k4^5x5z2/5B3L4)0H4$5w1I0d0c2,5#5T455-5L0(4)0e5_5S0(5:2`0n0o4S5b5o3M0-2l0u4k12535)3`4;59133H0C2s2T6l3q1m3s2v2x2t1T1V2v0r1D6o0v3r0/6B0S0U0W04.
Fonction droite

La fonction droite prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et décale le pointeur d'une case vers la droite. Sa valeur est donc augmentée de 1.

On garantit que cette action ne fera pas sortir de pointeur de l'intervalle \([\,\)0\(\,;\,\)9\(\,]\).

Cette fonction renvoie le dictionnaire modifié.

Exemple
>>> bf = {'programme': '>', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> droite(bf)
{'programme': '>', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 1, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgykP2o +]ualt/sbr[vce3)fh:1S=dp(050I0z0r0p0c0q0t0l0y0q0p0t0t0H010r0c0J010406050t0o0d0d0p0v0g040G0k0q0o0#0k0b050s0,0.0:0=0*0J040~1505180s181a150*0I0c0x0T0V0X0Z0D0c0f0D0q1o0D0r0(050O0u0q0z1j0W0Y011n1p1r1p0r1x1z1v0r0u0k0I0=1w0v160r0D0T0^0t0J0p0b0Z0j011B1l010C0Q0z0b0p0d0z1v1Z1#1*1D1-1z1:1=0(0a0l0i0v0k0J0k0t0c0{0b0l0M1X0v0v0z0y2a0~1^0b160s1V2n0r1T1S1U0I1`0Z1r0b1/271v1g1i0U1C2x0c2z0b1P1h1v0J2g162l2n2R0+1!2b2F1+2K0v0/0q0(0F2k2V0)2U1_2X1D2Z2#0(0j2)1#2+2l2w012:0p2$040A2@2m172P0~2D2q0I2u2{0y1P1?163719352T0 2*053c0M2Q2V2{0h0(0M0C323p2-1k1D0e0(0l3w2,2W3z0Z0b0C3t24290z3E2`2.0Z0%040K3P3q3R2|0(0u3v3k2^3F2{3T0B0E3w060l3:3D3Q3H3Z043#3W3y2G013T0w3{3G3}0t1(043~0k2I0r0z0o0v01413*0(0n3w3=3X3@0k0(0m0H4j3)3Y0d0c2%3.3;4k3|1+3s042g0r4c0}3%2m4z422Y3!3$2R0*0s3n0z2n2O4T361h382q2s2o1O1Q2q0p1y4W0s374Q0M0O0Q0t04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgykP2o +]ualt/sbr[vce3)fh:1S=dp(050I0z0r0p0c0q0t0l0y0q0p0t0t0H010r0c0J010406050t0o0d0d0p0v0g040G0k0q0o0#0k0b050s0,0.0:0=0*0J040~1505180s181a150*0I0c0x0T0V0X0Z0D0c0f0D0q1o0D0r0(050O0u0q0z1j0W0Y011n1p1r1p0r1x1z1v0r0u0k0I0=1w0v160r0D0T0^0t0J0p0b0Z0j011B1l010C0Q0z0b0p0d0z1v1Z1#1*1D1-1z1:1=0(0a0l0i0v0k0J0k0t0c0{0b0l0M1X0v0v0z0y2a0~1^0b160s1V2n0r1T1S1U0I1`0Z1r0b1/271v1g1i0U1C2x0c2z0b1P1h1v0J2g162l2n2R0+1!2b2F1+2K0v0/0q0(0F2k2V0)2U1_2X1D2Z2#0(0j2)1#2+2l2w012:0p2$040A2@2m172P0~2D2q0I2u2{0y1P1?163719352T0 2*053c0M2Q2V2{0h0(0M0C323p2-1k1D0e0(0l3w2,2W3z0Z0b0C3t24290z3E2`2.0Z0%040K3P3q3R2|0(0u3v3k2^3F2{3T0B0E3w060l3:3D3Q3H3Z043#3W3y2G013T0w3{3G3}0t1(043~0k2I0r0z0o0v01413*0(0n3w3=3X3@0k0(0m0H4j3)3Y0d0c2%3.3;4k3|1+3s042g0r4c0}3%2m4z422Y3!3$2R0*0s3n0z2n2O4T361h382q2s2o1O1Q2q0p1y4W0s374Q0M0O0Q0t04.
Fonction gauche

La fonction gauche prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et décale le pointeur d'une case vers la gauche. Sa valeur est donc diminuée de 1.

On garantit que cette action ne fera pas sortir de pointeur de l'intervalle \([\,\)0\(\,;\,\)9\(\,]\).

Cette fonction renvoie le dictionnaire modifié.

Exemple
>>> bf = {'programme': '<', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 1, 'sortie': ''}
>>> gauche(bf)
{'programme': '<', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgykP2o ]ualtb/sr[vce3)fh-:1S=dp(050I0y0q0o0c0p0t0l0x0p0o0t0t0H010q0c0J010406050t0n0d0d0o0u0g040G0k0p0n0#0k0b050s0,0.0:0=0*0J040~1505180s181a150*0I0c0w0T0V0X0Z0C0c0f0C0p1o0C0q0(050O0r0p0y1j0W0Y011n1p1r1p0q1x1z1v0q0r0k0I0=1w0u160q0C0T0^0t0J0o0b0Z0j011B1l010B0Q0y0b0o0d0y1v1Z1#1*1D1-1z1:1=0(0a0l0i0u0k0J0k0t0c0{0b0l0M1X0u0u0y0x2a0~1^0b160s1V2n0q1T1S1U0I1`0Z1r0b1/271v1g1i0U1C2x0c2z0b1P1h1v0J2g162l2n2R0+1!2b2F1+2K0u0/0p0(0F2k2V0)2U1_2X1D2Z2#0(0j2)1#2+2l2w012:0o2$040z2@2m172P0~2D2q0I2u2{0x1P1?163719352T0 2*053c0M2Q2V2{0h0(0M0B323p2-1k1D0e0(0l3w2,2W3z0Z0b0B0(0f0o0n0x0C0y3E2`2.0Z0%040K3S3q3U2|0(0r3v3k2^3F2{3W0A0E3w060l3?3D3T3H3$043(3Z3y2G013W0v3~3G400t1(04410k2I0q0y0n0u01443-0(0m3w3^3!3`0k0(0D0H4m3,3#0d0c2%3;3@4n3 1+3s042g0q4f0}3*2m4C452Y3%3)2R0*0s3n0y2n2O4W361h382q2s2o1O1Q2q0o1y4Z0s374T0M0O0Q0t04.
Fonction sortie

La fonction sortie prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et ajoute à la sortie le caractère correspondant à l'entier dans la case pointée actuellement.

On rappelle que la sortie stocke l'ensemble des caractères affichés. À l'issue de l'exécution cette variable contient l'ensemble des caractères affichés dans leur ordre d'affichage.

On rappelle que la fonction chr renvoie le caractère dont le code ASCII est passé en paramètre. On a ainsi chr(97) == 'a'.

Cette fonction renvoie le dictionnaire modifié.

Exemple
>>> bf = {'programme': '.', 'compteur': 0, 'mémoire': [97, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 1, 'sortie': ''}
>>> sortie(bf)
{'programme': '<', 'compteur': 0, 'mémoire': [97, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': 'a'}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk2Po 56]u+al4t/sbr[vce3)fh:1S=édp(050M0C0u0r0c0s0w0l0B0s0r0w0w0K010u0c0N010406050w0p0d0d0r0y0g040J0k0s0p0)0k0b050v0:0=0@0_0.0N041219051c0v1c1e190.0M0c0A0X0Z0#0%0G0c0f0G0s1s0G0u0,050S0x0s0C1n0!0$011r1t1v1t0u1B1D1z0u0x0k0M0_1A0y1a0u0G0X0|0w0N0r0b0%0i011F1p010F0U0C0b0r0d0C1z1%1)1.1H1;1D1@1_0,0a0l0j0y0k0N0k0w0c0 0b0l0Q1#0y0y0C0B2e121|0b1a0v1Z2r0u1X1W1Y0M1~0%1v0b1?2b1z1k1m0Y1G2B0c2D0b1T1l1z0N2k1a2p2r2V0/1(2f2J1/2O0y0?0s0,0I2o2Z0-2Y1}2#1H2%2)0,0i2-1)2/2p2A012@0r2*040D2{2q0.2~2=0%31330t362}2Z2 3c0,0m3f383h3a300k2(320,0n3f1b2T122H2u0M2y2 0B1T1`1a3A1d3y2X132.053F0Q2U3o1o1H0h0,0Q0F3w393U0%0e0,0l3!3T2K300F0,0w3r0)0C3+2;3$010+040O3^2!3`0b0,0x3Z3N2|2:403-3|0E0H3m0l4f3*3#3-42042a2M0u0C0p0y3f4h3,1/0k0,0K4s483i43452X4i1/3|0z3 2 0w1,043{0k4n4p0y014J3p3|0o4e4g4A3p4k1_0d4P2k4z4F1H4w044y462q4t3_4j4C4U3`4H4`3-4L0,010d0L4(0c2k4T4;3S4@4G0,4X58064g4?492$0,0B0@0r2m0C4*585h2 4.4:2V5s4#0x5k0G4r584!4{0,3~5D4,3b0,4%4)3@5I4u1H4|5P5a2?0,4m0b4o4q4}5b040o0E4Y4f5E4^04445#5R0,4I5T5i1H4 4N3;0y3?574E5Q0%4W4+61014.0q5v2.5x415k5m5o5q2V5f4Z5J013W042k0u4q115r5,5j5.4D2.0.0v3Q0C2r2S6B3z1l3B2u2w2s1S1U2u0r1C6E0v3A6y0Q0S0U0w04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk2Po 56]u+al4t/sbr[vce3)fh:1S=édp(050M0C0u0r0c0s0w0l0B0s0r0w0w0K010u0c0N010406050w0p0d0d0r0y0g040J0k0s0p0)0k0b050v0:0=0@0_0.0N041219051c0v1c1e190.0M0c0A0X0Z0#0%0G0c0f0G0s1s0G0u0,050S0x0s0C1n0!0$011r1t1v1t0u1B1D1z0u0x0k0M0_1A0y1a0u0G0X0|0w0N0r0b0%0i011F1p010F0U0C0b0r0d0C1z1%1)1.1H1;1D1@1_0,0a0l0j0y0k0N0k0w0c0 0b0l0Q1#0y0y0C0B2e121|0b1a0v1Z2r0u1X1W1Y0M1~0%1v0b1?2b1z1k1m0Y1G2B0c2D0b1T1l1z0N2k1a2p2r2V0/1(2f2J1/2O0y0?0s0,0I2o2Z0-2Y1}2#1H2%2)0,0i2-1)2/2p2A012@0r2*040D2{2q0.2~2=0%31330t362}2Z2 3c0,0m3f383h3a300k2(320,0n3f1b2T122H2u0M2y2 0B1T1`1a3A1d3y2X132.053F0Q2U3o1o1H0h0,0Q0F3w393U0%0e0,0l3!3T2K300F0,0w3r0)0C3+2;3$010+040O3^2!3`0b0,0x3Z3N2|2:403-3|0E0H3m0l4f3*3#3-42042a2M0u0C0p0y3f4h3,1/0k0,0K4s483i43452X4i1/3|0z3 2 0w1,043{0k4n4p0y014J3p3|0o4e4g4A3p4k1_0d4P2k4z4F1H4w044y462q4t3_4j4C4U3`4H4`3-4L0,010d0L4(0c2k4T4;3S4@4G0,4X58064g4?492$0,0B0@0r2m0C4*585h2 4.4:2V5s4#0x5k0G4r584!4{0,3~5D4,3b0,4%4)3@5I4u1H4|5P5a2?0,4m0b4o4q4}5b040o0E4Y4f5E4^04445#5R0,4I5T5i1H4 4N3;0y3?574E5Q0%4W4+61014.0q5v2.5x415k5m5o5q2V5f4Z5J013W042k0u4q115r5,5j5.4D2.0.0v3Q0C2r2S6B3z1l3B2u2w2s1S1U2u0r1C6E0v3A6y0Q0S0U0w04.
Fonction entree

La fonction entree prend en paramètre un dictionnaire décrivant l'état de l'interpréteur, demande à l'utilisateur de saisir un caractère ASCII et donne à la case pointée actuellement le code ASCII de ce caractère.

On rappelle que la fonction ord renvoie le code ASCII du caractère passé en paramètre. On a ainsi ord('a') == 97.

De plus, la fonction input permet de demander à l'utilisateur de saisir une chaîne de caractères et renvoie celle-ci.

Les entrées saisies dans les tests automatiques sont valides :

  • elles ne comportent qu'un unique caractère ;
  • le code ASCII de celui-ci est compris entre 0 et 255.

Lors de vos tests, vous devrez aussi respecter ces contraintes et ne pas saisir d'emoji par exemple ou de chaînes de deux caractères ou plus.

Cette fonction renvoie le dictionnaire modifié.

Exemple
>>> bf = {'programme': ',', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> entree(bf) # l'utilisateur saisit 'a' dont le code ASCII est 97
{'programme': ',', 'compteur': 0, 'mémoire': [97, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nximwOgyk2P;oC, 5à6]uRèalI4t/sbr[vce.3)Afh:1S=êéÀ_dqpD(050Z0K0C0y0d0z0E0q0J0z0y0E0E0U010C0d0#010406050E0v0e0e0y0G0i040T0n0z0v0{0n0b0q020y0e0#0m0q0w0K150G0!0v0K0E050D12141618100#041w1D051G0D1G1I1D100Z0d0I0:0=0@0_0Q0d0h0Q0z1W0Q0C0~050+0F0z0K1R0?0^011V1X1Z1X0C1)1+1%0C0F0n0Z181(0G1E0C0Q0:1b0E0#0y0b0_0k011-1T010P0-0K0b1j0K1%282a2f1/2i1+2l0e2n040a0q0l0G0n0#0n0E0d1e1g0)260G0G0K0J2I1w2p0b1E0D242U0C2221230Z2r0_1Z0b2k2F1%1O1Q0;1.2(0d2*0b1~1P1%0#2N1E2S2U2 11291g2:2g2^0G150z0~0S2R330 322q351/37390~0k3d2a3f2S2%013k0y3a040M3o2T103r3i0_3u3w0B3z3q333s3F0~0r3I3B3K3D3t0n383v0~0t3I1F2}1w2.2X0Z2#3s0J1~2x0(1P1E2|0K2~3e3Z3,0)3@3h1S1/0j0~0)0P3Z3C3~0_0f0~0q443R463t0P0~2k2Y0K0K4b3}2;010}040%4l344d0b0~0F431x3^454n4p0N0R3P0q4H4a4B360~2E2?0C0K0v0G3I4J4c4n0n0~0U4T3g4t4n4v044x4s3s4p0H4+3S0E2d044o0n4O4Q0G014/4d4p0u4G4I4#3L0~2w0e4^2N4!4K1/4X044Z4z3p4U4m4L4)4y315b0_4-4}4n4;0~010e0W570d2N4|5g2T533S4 514H5E4u0~0J160y2P0K595C045i4$2g5d5f2 5U3L0F0~2?0#1d5r2g4p4r5S5J5s4=010T0,2G0G0q0v345N2P0x2N0q0O0T0o0A0A0q0R0q5B5n4V5,0~0N5H5!3S4(56584k5/5o4o0~4.6o6d3j4M4^0b4P4R5+1/5G5S6i4d5X5a6u3E5$043U0Z6B5p0~5.6c5j6v045M0G5O4P5R6T5V6C6f6h5:2g40042N0C4R0b6I6U3E4w5m3e100D3`3?3!6 0D3%1w0C3)742Z2V1}1 2X0y1*713%1C3|6%0_2N0e0Y0P0y0j0K0Y0Q0M0~1o1q1s1u683Z1J3f1D0A0z0q1u0C0q4O0W2N0@2a7J2K0E000y1^160)5`125`0J7z0)0v0c0q1?2*0/2K0=2L2N2P0d1f7A7C1N1P3s1;1Y1!1$3;3#315/6~7i54046l5z6n5Z6+5c4Y6?7j3t6_6P6q046s6$3s5t4?5w5y5A8k6D2 3Q6@015d0L8C3P8d6^881p6m8v6r8k4(4N6y4`8K04506E8F8A8f8U6p0b6L6N8R6S4A6J8i6W5~6!8b8)8z4D8E6}3-2U3=2U7g1H040X7*000d0@1t0q7.0y0q3=0e0d601,0y0P0P2O0+2I0p7*970I160d7d1+4a6~7|1!1?1#2o8*6k8I8a7B85986x4P0q0I5Q0/9r0e0V2w0q1_0K0y0v0q7y9s3-9u1=7 9y8z4(4*6t8;8L9*8h8q5v5x6m6b8:8h8w3^8@3{684J2Y1f0h882_2i5Q905|0q571Oa40q9T0@0d909T4i2R9 0ba10L1F7D040$1f0J9l0q0E2O1f2K9e9g2P7U7?1g059t3S7}9w808V9A8t8/3p8V5q9-878O6z4SaT5F0~8T8c6p6H8Y9z8#0G6OaY4~6R8M5L8-5QaP5D6p8=5/9{3?7H0E7J0W1s1P3v4h1,0s9X2KaI9v9#866j8ja.4C9,8o4:5=8s9=8R0u8n9@aU9G8Qbh6e8S8g3sa(a$a*0~8$bw6(4qa;8,6Y5P6#bsaZ046ga|850L0q0g1g970J0Q4^2G7Q001d0-92a57/9n0G9p7eac7(b*0,61aG9Ybb9!1@9$8haN8JbS8^ac2i2J7T0z0z0W0ha57#1^1,2^9iaEan7_3$0*0,0.04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nximwOgyk2P;oC, 5à6]uRèalI4t/sbr[vce.3)Afh:1S=êéÀ_dqpD(050Z0K0C0y0d0z0E0q0J0z0y0E0E0U010C0d0#010406050E0v0e0e0y0G0i040T0n0z0v0{0n0b0q020y0e0#0m0q0w0K150G0!0v0K0E050D12141618100#041w1D051G0D1G1I1D100Z0d0I0:0=0@0_0Q0d0h0Q0z1W0Q0C0~050+0F0z0K1R0?0^011V1X1Z1X0C1)1+1%0C0F0n0Z181(0G1E0C0Q0:1b0E0#0y0b0_0k011-1T010P0-0K0b1j0K1%282a2f1/2i1+2l0e2n040a0q0l0G0n0#0n0E0d1e1g0)260G0G0K0J2I1w2p0b1E0D242U0C2221230Z2r0_1Z0b2k2F1%1O1Q0;1.2(0d2*0b1~1P1%0#2N1E2S2U2 11291g2:2g2^0G150z0~0S2R330 322q351/37390~0k3d2a3f2S2%013k0y3a040M3o2T103r3i0_3u3w0B3z3q333s3F0~0r3I3B3K3D3t0n383v0~0t3I1F2}1w2.2X0Z2#3s0J1~2x0(1P1E2|0K2~3e3Z3,0)3@3h1S1/0j0~0)0P3Z3C3~0_0f0~0q443R463t0P0~2k2Y0K0K4b3}2;010}040%4l344d0b0~0F431x3^454n4p0N0R3P0q4H4a4B360~2E2?0C0K0v0G3I4J4c4n0n0~0U4T3g4t4n4v044x4s3s4p0H4+3S0E2d044o0n4O4Q0G014/4d4p0u4G4I4#3L0~2w0e4^2N4!4K1/4X044Z4z3p4U4m4L4)4y315b0_4-4}4n4;0~010e0W570d2N4|5g2T533S4 514H5E4u0~0J160y2P0K595C045i4$2g5d5f2 5U3L0F0~2?0#1d5r2g4p4r5S5J5s4=010T0,2G0G0q0v345N2P0x2N0q0O0T0o0A0A0q0R0q5B5n4V5,0~0N5H5!3S4(56584k5/5o4o0~4.6o6d3j4M4^0b4P4R5+1/5G5S6i4d5X5a6u3E5$043U0Z6B5p0~5.6c5j6v045M0G5O4P5R6T5V6C6f6h5:2g40042N0C4R0b6I6U3E4w5m3e100D3`3?3!6 0D3%1w0C3)742Z2V1}1 2X0y1*713%1C3|6%0_2N0e0Y0P0y0j0K0Y0Q0M0~1o1q1s1u683Z1J3f1D0A0z0q1u0C0q4O0W2N0@2a7J2K0E000y1^160)5`125`0J7z0)0v0c0q1?2*0/2K0=2L2N2P0d1f7A7C1N1P3s1;1Y1!1$3;3#315/6~7i54046l5z6n5Z6+5c4Y6?7j3t6_6P6q046s6$3s5t4?5w5y5A8k6D2 3Q6@015d0L8C3P8d6^881p6m8v6r8k4(4N6y4`8K04506E8F8A8f8U6p0b6L6N8R6S4A6J8i6W5~6!8b8)8z4D8E6}3-2U3=2U7g1H040X7*000d0@1t0q7.0y0q3=0e0d601,0y0P0P2O0+2I0p7*970I160d7d1+4a6~7|1!1?1#2o8*6k8I8a7B85986x4P0q0I5Q0/9r0e0V2w0q1_0K0y0v0q7y9s3-9u1=7 9y8z4(4*6t8;8L9*8h8q5v5x6m6b8:8h8w3^8@3{684J2Y1f0h882_2i5Q905|0q571Oa40q9T0@0d909T4i2R9 0ba10L1F7D040$1f0J9l0q0E2O1f2K9e9g2P7U7?1g059t3S7}9w808V9A8t8/3p8V5q9-878O6z4SaT5F0~8T8c6p6H8Y9z8#0G6OaY4~6R8M5L8-5QaP5D6p8=5/9{3?7H0E7J0W1s1P3v4h1,0s9X2KaI9v9#866j8ja.4C9,8o4:5=8s9=8R0u8n9@aU9G8Qbh6e8S8g3sa(a$a*0~8$bw6(4qa;8,6Y5P6#bsaZ046ga|850L0q0g1g970J0Q4^2G7Q001d0-92a57/9n0G9p7eac7(b*0,61aG9Ybb9!1@9$8haN8JbS8^ac2i2J7T0z0z0W0ha57#1^1,2^9iaEan7_3$0*0,0.04.
Fonction fermant_correspondant

La fonction fermant_correspondant prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et modifie le compteur afin de lui donner la valeur de l'indice dans le programme du crochet fermant correspondant.

Cette fonction recherche l'indice du crochet fermant et correspondant et pas celui de l'instruction suivante. C'est la fonction interpreteur qui se chargera de décaler cette valeur d'une unité.

Cette fonction renvoie le dictionnaire passé en paramètre.

Attention, les programmes Brainfuck utilisent beaucoup de crochets et bien souvent ceux-ci sont imbriqués comme dans "[->[+<]]"2. Dans cet exemple :

  • si on appelle la fonction fermant_correspondant alors que l'interpréteur désigne le premier crochet ouvrant, elle doit renvoyer l'indice du dernier ;

  • si on appelle la fonction fermant_correspondant alors que l'interpréteur désigne le deuxième crochet ouvrant, elle doit renvoyer l'indice de l'avant-dernier.

On garantit que lorsque la fonction fermant_correspondant est appelée, le compteur de l'interpréteur désigne une instruction "[".

On garantit de plus que les programmes proposés sont bien formés (les crochets sont bien structurés et l'on ne rencontre pas de cas tels que "[[]" ou "][").

Aide

Une approche consiste à utiliser une variable, que l'on pourra nommer pile, qui tient le compte des crochets rencontrés. On initialise cette variable à la valeur +1 puis on progresse dans le programme. Si l'instruction lue est un crochet ouvrant on incrémente pile, si c'est un crochet fermant on la décrémente.

Lorsque pile vaut 0 on a trouvé le crochet fermant correspondant à l'ouvrant de départ.

Exemples
>>> bf = {"programme": "[->[+<]]", "compteur": 0, "mémoire": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "pointeur": 0,"sortie": "",}
>>> fermant_correspondant(bf)
{'programme': '[->[+<]]', 'compteur': 7, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> bf = {"programme": "[->[+<]]", "compteur": 3, "mémoire": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "pointeur": 0,"sortie": "",}
>>> fermant_correspondant(bf)
{'programme': '[->[+<]]', 'compteur': 6, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk02Po 56]u+al84t/sbr[vce!3)fh-:1S=97_dp(050S0E0w0s0c0t0y0m0D0t0s0y0y0O010w0c0T010406050y0q0d0d0s0A0g040N0l0t0q0/0l0b050x0_0{0}0 0@0T04181f051i0x1i1k1f0@0S0c0C0%0)0+0-0J0c0f0J0t1y0J0w0=050Y0z0t0E1t0*0,011x1z1B1z0w1H1J1F0w0z0l0S0 1G0A1g0w0J0%120y0T0s0b0-0j011L1v010I0!0E0b0s0d0E1F1-1/1@1N1`1J1}1 0=0a0m0k0A0l0T0l0y0c150b0m0W1+0A0A0E0D2k18220b1g0x1)2x0w1%1$1(0S240-1B0b1|2h1F1q1s0(1M2H0c2J0b1Z1r1F0T2q1g2v2x2#0^1.2l2P1^2U0A0|0t0=0m0M2u2)0?2(232+1N2-2/2;0j2@1/2_2v2G012~0s2:040m0G322w0@352|0-383a0m0v3e342)363k2;0n3o3g3q3i370l2.392;0o3v2`2*1u2}3A2 3b0Q3F3h3I3j3K3C3b0u3O3x3Q3z3B3l0P3W2{3Y3s040M0i3%3H2Q3Z3L0M2?192^3w3(3:3*0M313^331h2Z182N2A0S2E360D1Z201g451j432%402w054a0W2!3X3:0h0=0W0I3o3G360e2;4u3P3|0I0=0I0E3B0b0w0R4a2p0E1-160S1/0w4z4o1^0;040U4S3{2,0=0z4t4i4n4Z1N4V0H0L3v0m4:0m4v3y0b0=4a0d0T0w0E0q0A3o4=4A1^0l0=0O514?3)4#4%2%534+0=0B4Y3/1^0y1=04014`4|4~0A015i364V0p4/4;593|0=2Y0l0f0A1~1 585e0-5504574(524T2}5b5u3y4V5h4(5A5k5m015D5F5H205U3Y5w5y4:5Z5S040T1{5J5R5L565^4*0-0d0c0=3@2#064;5Q5}014q040e1x1J5|5j5;5?6d5P5:5`040F5O2#666f5~60043-5Y5K5$0=4.4(64655z6x4^045p4}4 6e365M0r6o2^6q365 615.6D6k680=0c5c6Q6X6G5%5G0{0E5+3:5W6-4!6H0l4{6J506w5_6y045x6j6x5M0O6P336R3y5l0=010p5t6`674V6A636D7h755a5=5@6 6{5M0K732w7j3:6T3+6V656X690E1B6#746%5C2e5(6+6:5f045X5d6{6G6I5r7K0-5-7n67717r3b6X775n0B7b7O7d6z7x7i7F7l6i6p6X6N7Z7t1^7v623_7y6F5T7c6r6|7N2^7#5#7R4 7)856x7V7=705{7W827Q6?5q6K6B7~6{692q0w4 178h3r8063184l0E2x2Y8B441r462A2C2y1Y1!2A0s1I8E0x450@8R0X0Z0#04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk02Po 56]u+al84t/sbr[vce!3)fh-:1S=97_dp(050S0E0w0s0c0t0y0m0D0t0s0y0y0O010w0c0T010406050y0q0d0d0s0A0g040N0l0t0q0/0l0b050x0_0{0}0 0@0T04181f051i0x1i1k1f0@0S0c0C0%0)0+0-0J0c0f0J0t1y0J0w0=050Y0z0t0E1t0*0,011x1z1B1z0w1H1J1F0w0z0l0S0 1G0A1g0w0J0%120y0T0s0b0-0j011L1v010I0!0E0b0s0d0E1F1-1/1@1N1`1J1}1 0=0a0m0k0A0l0T0l0y0c150b0m0W1+0A0A0E0D2k18220b1g0x1)2x0w1%1$1(0S240-1B0b1|2h1F1q1s0(1M2H0c2J0b1Z1r1F0T2q1g2v2x2#0^1.2l2P1^2U0A0|0t0=0m0M2u2)0?2(232+1N2-2/2;0j2@1/2_2v2G012~0s2:040m0G322w0@352|0-383a0m0v3e342)363k2;0n3o3g3q3i370l2.392;0o3v2`2*1u2}3A2 3b0Q3F3h3I3j3K3C3b0u3O3x3Q3z3B3l0P3W2{3Y3s040M0i3%3H2Q3Z3L0M2?192^3w3(3:3*0M313^331h2Z182N2A0S2E360D1Z201g451j432%402w054a0W2!3X3:0h0=0W0I3o3G360e2;4u3P3|0I0=0I0E3B0b0w0R4a2p0E1-160S1/0w4z4o1^0;040U4S3{2,0=0z4t4i4n4Z1N4V0H0L3v0m4:0m4v3y0b0=4a0d0T0w0E0q0A3o4=4A1^0l0=0O514?3)4#4%2%534+0=0B4Y3/1^0y1=04014`4|4~0A015i364V0p4/4;593|0=2Y0l0f0A1~1 585e0-5504574(524T2}5b5u3y4V5h4(5A5k5m015D5F5H205U3Y5w5y4:5Z5S040T1{5J5R5L565^4*0-0d0c0=3@2#064;5Q5}014q040e1x1J5|5j5;5?6d5P5:5`040F5O2#666f5~60043-5Y5K5$0=4.4(64655z6x4^045p4}4 6e365M0r6o2^6q365 615.6D6k680=0c5c6Q6X6G5%5G0{0E5+3:5W6-4!6H0l4{6J506w5_6y045x6j6x5M0O6P336R3y5l0=010p5t6`674V6A636D7h755a5=5@6 6{5M0K732w7j3:6T3+6V656X690E1B6#746%5C2e5(6+6:5f045X5d6{6G6I5r7K0-5-7n67717r3b6X775n0B7b7O7d6z7x7i7F7l6i6p6X6N7Z7t1^7v623_7y6F5T7c6r6|7N2^7#5#7R4 7)856x7V7=705{7W827Q6?5q6K6B7~6{692q0w4 178h3r8063184l0E2x2Y8B441r462A2C2y1Y1!2A0s1I8E0x450@8R0X0Z0#04.
Fonction ouvrant_correspondant

On conseille d'avoir bien compris la question précédente avant d'aborder celle-ci.

La fonction ouvrant_correspondant prend en paramètre un dictionnaire décrivant l'état de l'interpréteur et modifie le compteur afin de lui donner la valeur de l'indice dans le programme du crochet ouvrant correspondant.

Comme dans la fonction précédente, cette fonction fonction décale le pointeur jusqu'au crochet correspondant, pas jusqu'à l'instruction qui le suit.

Cette fonction renvoie le dictionnaire passé en paramètre.

On garantit que lorsque la fonction ouvrant_correspondant est appelée, le compteur de l'interpréteur désigne une instruction "]".

On garantit de plus que les programmes proposés sont bien formés (les crochets sont bien structurés et l'on ne rencontre pas de cas tels que "[[]" ou "][").

Exemples
>>> bf = {"programme": "[->[+<]]", "compteur": 7, "mémoire": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "pointeur": 0,"sortie": "",}
>>> ouvrant_correspondant(bf)
{'programme': '[->[+<]]', 'compteur': 0, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}
>>> bf = {"programme": "[->[+<]]", "compteur": 6, "mémoire": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "pointeur": 0,"sortie": "",}
>>> ouvrant_correspondant(bf)
{'programme': '[->[+<]]', 'compteur': 3, 'mémoire': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'pointeur': 0, 'sortie': ''}

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nimwgyk02Po 56]u+al84t/sbr[vce!3)fh-:1S=97_dp(050S0E0w0s0c0t0y0m0D0t0s0y0y0O010w0c0T010406050y0q0d0d0s0A0g040N0l0t0q0/0l0b050x0_0{0}0 0@0T04181f051i0x1i1k1f0@0S0c0C0%0)0+0-0J0c0f0J0t1y0J0w0=050Y0z0t0E1t0*0,011x1z1B1z0w1H1J1F0w0z0l0S0 1G0A1g0w0J0%120y0T0s0b0-0j011L1v010I0!0E0b0s0d0E1F1-1/1@1N1`1J1}1 0=0a0m0k0A0l0T0l0y0c150b0m0W1+0A0A0E0D2k18220b1g0x1)2x0w1%1$1(0S240-1B0b1|2h1F1q1s0(1M2H0c2J0b1Z1r1F0T2q1g2v2x2#0^1.2l2P1^2U0A0|0t0=0m0M2u2)0?2(232+1N2-2/2;0j2@1/2_2v2G012~0s2:040m0G322w0@352|0-383a0m0v3e342)363k2;0n3o3g3q3i370l2.392;0o3v2`2*1u2}3A2 3b0Q3F3h3I3j3K3C3b0u3O3x3Q3z3B3l0P3W2{3Y3s040M0i3%3H2Q3Z3L0M2?192^3w3(3:3*0M313^331h2Z182N2A0S2E360D1Z201g451j432%402w054a0W2!3X3:0h0=0W0I3o3G360e2;4u3P3|0I0=0l0q0C0A1/0w0R4a2p0E1-160S4I4z4o1^0;040U4S3{2,0=0z4t4i4n4Z1N4V0H0L3v0m4:0m4v3y0b0=4a0d0T0w0E0q0A3o4=4A1^0l0=0O514?3)4#4%2%534+0=0B4Y3/1^0y1=04014`4|4~0A015i364V0p4/4;593|0=2Y0l0f4H0{0E585e0-5504574(524T2}5b5u3y4V5h4(5A5k5m015D5F1~295U3Y5w5y4:5Z5S040T1{5J5R5L565^4*5`040K5+3:0d0c0=3@2#064;5Q5}014q040e1x1J5|5j5;5?6h5P5:5~0F5O2#6a6j0-630=3-5Y5K5$0=4.4(68695z6A4^045p4}4 6i365M0K6r2^6t366w3+5.6G6o6c0=0c5c6T6!6J5%5G1 614U5g6/5;6L5r6=0-5-6n6A5M0O6S336U3y5l0=010p5t6z5_6B046D676G7f725a5=5@6|7a6Q702w7h62646X6E7g7q1^6d0E1B6(716*5C2e5(5H6_7b5X5d7a6J6@6N796b6{6s6!6~7o3b6!745n0B787L7R6C6Y7v7D7j6m7T6}0=0r7W7w1N6W663_697,4$7I5W7I7Z5o0l4{6M5s7 0=5x7l6b6~6O4@4_845q7P7e6H7a6d2q0w4 178b6u375T6E184l0E2x2Y8z441r462A2C2y1Y1!2A0s1I8C0x450@8P0X0Z0#04.
Fonction interpreteur

À ce stade, nous avons écrit la fonction permettant d'initialiser l'interpréteur et celles correspondants à chacune des instructions. Nous pouvons donc écrire l'interpréteur, enfin !

La fonction interpreteur prend en paramètre un programme Brainfuck, crée le dictionnaire décrivant son état puis exécute le programme. Elle renvoie l'état final de la sortie.

Une version valide de chacune des différentes fonctions étudiées plus haut est déjà chargée dans l'éditeur. Vous pouvez donc les utiliser directement, sans avoir à les importer.

Une fois l'initialisation de l'interpréteur effectuée, cette fonction s'organise autour d'une boucle Tant que :

Algorithme simplifié
Fonction interpreteur(programme):
    Initialiser l'état de l'interpréteur
    Tant que le compteur n'a pas atteint la fin du programme:
        Lire l'instruction à effectuer
        Effectuer cette instruction en envisageant les 8 cas possibles
        Incrémenter le compteur
    Renvoyer la sortie de l'interpréteur

On n'oubliera pas de relire les définitions des instructions, en particulier celles relatives aux crochets.

Exemples

Comme son nom l'indique, le premier programme testé effectue l'addition 3 + 2 et affiche le résultat. Le caractère résultant, de code ASCII 5, n'est pas affichable dans la console (il s'agit du caractère ENQ). Python l'affiche donc en hexadécimal '\x05' (en effet \(05_{16}=5_{10}\)).

>>> trois_plus_deux = "+++>++[-<+>]<."
>>> interpreteur(trois_plus_deux)
'\x05'
>>> affiche_coucou = "+" * 99 + ".>" + "+" * 111 + ".>" + "+" * 117 + ".<<.>.>."
>>> interpreteur(affiche_coucou)
'coucou'

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nFTmwOgPoC,}6]uRa8bsr[vce!-1S9_d(Liyk02; 5à+lI4t/.3)fh{:=êé7qNp050G0z0W0r0J0T0u0P0y0T0r0u0u0)010W0J0/010406050u0p0e0e0r0v0K040D0j0T0p130j0b0P020r0e0/0O0P0q0z1d0v0-0p0z0u050X1a1c1e1g180/041E1L051O0X1O1Q1L180G0J0x0{0}0 110$0J0h0$0T1(0$0W16050?0t0T0z1Z0~10011%1)1+1)0W1;1?1/0W0t0j0G1g1:0v1M0W0$0{1j0u0/0r0b110N011^1#010#0^0z0b1r0z1/2g2i2n1`2q1?2t0e2v040a0P0i0v0j0/0j0u0J1m1o0;2e0v0v0z0y2Q1E2x0b1M0X2c2$0W2a292b0G2z111+0b2s2N1/1W1Y0|1_2:0J2=0b261X1/0/2V1M2!2$37192h1o2{2o300v1d0T160P0C2Z3b173a2y3d1`3f3h3j0N3m2i3o2!2/013t0r3i040P0Z3x2#183A3r113D3F0P0V3J3z3b3B3P3j0Q3T3L3V3N3C0j3g3E3j0n3!3p3c1!3s3)3u3G0,3.3M3;3O3?3+3G0s3`3$3|3(3*3Q0E423q443X040C0M493:2|453@0C3l1F3n3#4a4i4c0C3w4n3y4p4h3e3~3F0C3I4v3K3/3W4A160C3S4E3U4q4z464J3Z4M4x4H4Q4d3-4T4G3%4s3_4Z3{4r4I4d414(434*4W0C484.4O3=4W0N4f4@4y4_3@0N4m374U4#4+0N4u391R351E2_2)0G2-3B0y262F0:1X1M340z363n3T055i0;5q4^110L160;0#5s4)2o0f3j5D4/3e0#162~0W0z0v5o5O0p0v5I5x0115040H5V4~3O16340j0h0v1r2E5#3B5Y0!0(3!0P5^0P4!4b160t5C4M5`5E1`0j160)3T615J3s160y2V0r2Y4M5{4i5Y5!6g625%045)5+5-0z5/3%5;5@5_6h2o5z040f1%1?676y6a045~6t445Y0w6K4i0u2l04015i1s5S0v016O2o5Y0o6F6m016404020T0W0O6%693O0t162C6Z1`6j6_6n6p5,1c6s6l6;5X165=6w5_6x6(0b5M0b0u2*0p2X0J1n6:5W6*66606G6}2K6q706|74046N725W7b6I5 396(6M7u6Q166T0j6V0z5T6Y7y5$7v0o6$4T78787p016A0J7C3n687z7c7e0v7g6f377%7Q7m7n7.7X7H6S020h6.7O7D735Y5?7U7V837X7A6J7o6(7m7k7Q7A0G2K2P717~5W6{7P3W5}7#3y7X6v82846(6A0z1+8o2#7/8m042~7*7,7i0b8b3B7;8I3%7^016,7|7u8077837973868y3G7X8a888W160h0r7g0$8h5r7E166k8i8c8n8R758T7W8u168w7!8L5|8C7d7f7h7j8$7l657=7$7@6R010S7}8.7 1681538U7V858@977:65904r7c6c1x2s5O8^5Z7u8X9A0!8`8V5W8v8x9t3e7)947-9b89999L1`8N0B9g8p8/049k4o9m8{8%7B9T118#7?7a5A2W2V2E0b9z8l6u8:9C9p8=5:8_8s9n8|048~8Y8A4#9N7+958H9q8J9Sad8M9d0Y9X2#8q9j9G8t9)879.739-9Q9)0u3)138-9Y9i9B9_91ar9h8ja09l8U7X9J8 ag918D9O8G9+6)afas5W8N0lak5w7Q8Sa19m9o9*aP4iau3ya7919y2VaAal9Z8;aH8?a,9~9`049Fa)9H7QaNa6a+aRaa9Pa:8!aWavaY9d0wa#a;a.5G042i0GaU9DaE6i167xa 448N0e0+0e0j0J2Va#am040obva|8BaGaBaI7w7G9d2M5N7M6X9A7SaU8Ka-2o0e0J164|bwbt9!aoa2aqb79R049abc9/040#5P1d9@0F5i2U1C2M0b0G2i0W9Aa{bNa}bMa_aCb2aKap9I8}9Kb!6Hb98F96aX9rb=b?8z9c7I0obj8!bmbobq9}bKb0bJc93BbybAbCbEbWcFcc7(a~cD6LbubQ7IbS9@bUbF9ZbXck9,160Acs8Z6(b$b(9A9#4w9%b4bLb:at9sc$3C160j0p0x5,b}b 2V2g1nc49@c79|cQcGb0ce9$aLb^cba$9 bPbs2o8N6U0/6WcZaC7Tcpae040Sc*bkb#b%4d8TaM162V0W5Tacdva8dbcOa%cTdm9U9dax0vazdsbOdu4o1E5u5p1N5b0X5d1E0W5fd,2+2%25272)0r1=d%d*5m1Kdj3%9=0F0#0r0L0z0F0$0Z161w1y1A1C0Pc:al1R3o1L0I1@d$0P5)2M0u0+0P2s2T2Vabes7e0P0v0+0/0+13130#ee0{0$0r0y0p2Red0$0p2P0{0~ez0z5oc30P0}0P0e0*2E0P8E2X5T0z0l0PeM0P5Oey1a1X0J0P0G00e/0r0/0/8w0P0ReY0r0P0#1newd3c1d6c50z0Y1Nei040U0Tex0Wen2N2Od_e_003)8)0b0J0u5PeYel5je_7!0#0+9=9?fl0r2qeNeY003E0T0+0h5P0Y0P0g1o1l0^fv1@2M5T0{1@e2bD1@e/1Wab2tf)0P1_0j0y0Jc5f1eI0rec0Pcmew0uf4f60babfSfif58*fl0Wc~5Of6fven2Vc32Ve(bCfKbB1W2qfx1?0`g2ab0`0hfEf^gq0{2K0y8,0W0`fI2~e_1@e;5O0vfy0`0x3EbU0`cW0W0+edd70`0y8wgq0Bf?feehd}ek2e2Sdp1?fl0;0x0J9yeeff1V1X3B1|1*1,1.5n5b5939d$d~446A5B7ubm5`dR3O5Lb_b{c5b~3)d4c2d7c6hc7vc8dOc@9Eef179(ch8Cc^cPdibGcNh56P9dbzbBf)dXdPbHhDa+hB9ZhN6(8NgScYbWdZb@c_craUc-04b)cRb+hu5^7X0y0C1603fye:1Cflh@f}9@fPeAf_eZgsbb3Ka*b^dp6WbYc`dLaF8YhCcU6Si5hVho6#b-a+6~6ri7b=cBdNhE6!dQb*dnbR7r6 2EhKdkhXi2dg9)0/2rindz7Xh$52dfcgb5166CiHc{7AiG6Ec{6*c)h#dCh(dccSb,b3iO8Bif5Tindyi!4Jb-hwiPhyipil7tihith)9M04i-5Ui}bHiIiJhS9dcwc/i?iEcPiVa^c+hZ0Bj773iLjch,a3a5i`iximj4hR9)j2bWj6aU8Nbijbi*9%ikiSi9a.16i:c{jmjEhOibhQid7J7L7NjyiXi8bfa}jxa1dF04dHdJipdi06j-j%h8hoha9Chec~d0hhf9d5c3c5d9hobriu6`75hu06i@3B7ZhzcajQaCjvbg7IhHcK2vcMdahPkdjShUjVj4c#jI2oiYjk5Wh$i$hrb0h+dA1`h.h:h=gJfkh`gT5+erf2h f7i1hvjdj!7KdqbUiIj+kcbOke7QdokVdrjWcfb.jejsi|kt63jYhYhAk!hLk$cHiw5*iykjkrijb^jfkYjX040B7ujNk,k73%6AiRiWk;6}jHjZdwiZjMi#jDlbkTi,k)kXl6jji;dDjElch65Mka8Bi{5.judaj#k211iil60)kwk%j9iAkBjnk-a}l4lvlP3BlaiNjFjpcjlhc|6ok/lGlK7vk{dMlJi k3j5lNlZah7IjCj4k5c=i+dMlXl*6*jLl*l#c;lrdMkmk#jSj2lSi(iCjh98ioiT6blti.j$a3j)0vdKlkmc8Yj-j.b^0c0g0.0k0d0UmD0Dl5l*5Y0%dEj87I7`8Ql ip8ebC9^l/5Y0lmO738N8P0Omhh*ip8)8+jgbGm!mrm$9d9flpmwaQg39=9ym/9Zm;k,cu6S9Wm_k@a}0;9wfGm aCn1l$n301ajn6ctb^dUaz9Anemajom?7Ia!njmka}a?0zncbOnpiDnrkf6Sl~mYanmnhf3*d2hjfaj}d8j4nCkSnElQcvm*isi)l*7Aj^d10Whic0j|hmno4gdk0m3!54lB04j:l/j=k0hebT5QdHlunIaDl/iUl-nAhL76m=k^mKm`9uj16dkRbGhqir6HlFo7dkdenqkD5yiQ6Djgorl+mdk`mfmpbVl1l6m(bq6?046^j4ojiko6htl29)f~kRowa/nkiFoNlHk0cCi%b+l;bx9dmghWoPcPlD3%oUnw8BmCmEmGmI9Ao%oeoRaToDlqnVhslNipk_dkoLdhp5ddo,kbo`oAjUoCo2mjoTjKl{44m9nDow6Amtmvn7p2o2o{iv7Inmg=nYl^mj180Xh4d(d`5dpE0;0?0^0u04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.128013nFTmwOgPoC,}6]uRa8bsr[vce!-1S9_d(Liyk02; 5à+lI4t/.3)fh{:=êé7qNp050G0z0W0r0J0T0u0P0y0T0r0u0u0)010W0J0/010406050u0p0e0e0r0v0K040D0j0T0p130j0b0P020r0e0/0O0P0q0z1d0v0-0p0z0u050X1a1c1e1g180/041E1L051O0X1O1Q1L180G0J0x0{0}0 110$0J0h0$0T1(0$0W16050?0t0T0z1Z0~10011%1)1+1)0W1;1?1/0W0t0j0G1g1:0v1M0W0$0{1j0u0/0r0b110N011^1#010#0^0z0b1r0z1/2g2i2n1`2q1?2t0e2v040a0P0i0v0j0/0j0u0J1m1o0;2e0v0v0z0y2Q1E2x0b1M0X2c2$0W2a292b0G2z111+0b2s2N1/1W1Y0|1_2:0J2=0b261X1/0/2V1M2!2$37192h1o2{2o300v1d0T160P0C2Z3b173a2y3d1`3f3h3j0N3m2i3o2!2/013t0r3i040P0Z3x2#183A3r113D3F0P0V3J3z3b3B3P3j0Q3T3L3V3N3C0j3g3E3j0n3!3p3c1!3s3)3u3G0,3.3M3;3O3?3+3G0s3`3$3|3(3*3Q0E423q443X040C0M493:2|453@0C3l1F3n3#4a4i4c0C3w4n3y4p4h3e3~3F0C3I4v3K3/3W4A160C3S4E3U4q4z464J3Z4M4x4H4Q4d3-4T4G3%4s3_4Z3{4r4I4d414(434*4W0C484.4O3=4W0N4f4@4y4_3@0N4m374U4#4+0N4u391R351E2_2)0G2-3B0y262F0:1X1M340z363n3T055i0;5q4^110L160;0#5s4)2o0f3j5D4/3e0#162~0W0z0v5o5O0p0v5I5x0115040H5V4~3O16340j0h0v1r2E5#3B5Y0!0(3!0P5^0P4!4b160t5C4M5`5E1`0j160)3T615J3s160y2V0r2Y4M5{4i5Y5!6g625%045)5+5-0z5/3%5;5@5_6h2o5z040f1%1?676y6a045~6t445Y0w6K4i0u2l04015i1s5S0v016O2o5Y0o6F6m016404020T0W0O6%693O0t162C6Z1`6j6_6n6p5,1c6s6l6;5X165=6w5_6x6(0b5M0b0u2*0p2X0J1n6:5W6*66606G6}2K6q706|74046N725W7b6I5 396(6M7u6Q166T0j6V0z5T6Y7y5$7v0o6$4T78787p016A0J7C3n687z7c7e0v7g6f377%7Q7m7n7.7X7H6S020h6.7O7D735Y5?7U7V837X7A6J7o6(7m7k7Q7A0G2K2P717~5W6{7P3W5}7#3y7X6v82846(6A0z1+8o2#7/8m042~7*7,7i0b8b3B7;8I3%7^016,7|7u8077837973868y3G7X8a888W160h0r7g0$8h5r7E166k8i8c8n8R758T7W8u168w7!8L5|8C7d7f7h7j8$7l657=7$7@6R010S7}8.7 1681538U7V858@977:65904r7c6c1x2s5O8^5Z7u8X9A0!8`8V5W8v8x9t3e7)947-9b89999L1`8N0B9g8p8/049k4o9m8{8%7B9T118#7?7a5A2W2V2E0b9z8l6u8:9C9p8=5:8_8s9n8|048~8Y8A4#9N7+958H9q8J9Sad8M9d0Y9X2#8q9j9G8t9)879.739-9Q9)0u3)138-9Y9i9B9_91ar9h8ja09l8U7X9J8 ag918D9O8G9+6)afas5W8N0lak5w7Q8Sa19m9o9*aP4iau3ya7919y2VaAal9Z8;aH8?a,9~9`049Fa)9H7QaNa6a+aRaa9Pa:8!aWavaY9d0wa#a;a.5G042i0GaU9DaE6i167xa 448N0e0+0e0j0J2Va#am040obva|8BaGaBaI7w7G9d2M5N7M6X9A7SaU8Ka-2o0e0J164|bwbt9!aoa2aqb79R049abc9/040#5P1d9@0F5i2U1C2M0b0G2i0W9Aa{bNa}bMa_aCb2aKap9I8}9Kb!6Hb98F96aX9rb=b?8z9c7I0obj8!bmbobq9}bKb0bJc93BbybAbCbEbWcFcc7(a~cD6LbubQ7IbS9@bUbF9ZbXck9,160Acs8Z6(b$b(9A9#4w9%b4bLb:at9sc$3C160j0p0x5,b}b 2V2g1nc49@c79|cQcGb0ce9$aLb^cba$9 bPbs2o8N6U0/6WcZaC7Tcpae040Sc*bkb#b%4d8TaM162V0W5Tacdva8dbcOa%cTdm9U9dax0vazdsbOdu4o1E5u5p1N5b0X5d1E0W5fd,2+2%25272)0r1=d%d*5m1Kdj3%9=0F0#0r0L0z0F0$0Z161w1y1A1C0Pc:al1R3o1L0I1@d$0P5)2M0u0+0P2s2T2Vabes7e0P0v0+0/0+13130#ee0{0$0r0y0p2Red0$0p2P0{0~ez0z5oc30P0}0P0e0*2E0P8E2X5T0z0l0PeM0P5Oey1a1X0J0P0G00e/0r0/0/8w0P0ReY0r0P0#1newd3c1d6c50z0Y1Nei040U0Tex0Wen2N2Od_e_003)8)0b0J0u5PeYel5je_7!0#0+9=9?fl0r2qeNeY003E0T0+0h5P0Y0P0g1o1l0^fv1@2M5T0{1@e2bD1@e/1Wab2tf)0P1_0j0y0Jc5f1eI0rec0Pcmew0uf4f60babfSfif58*fl0Wc~5Of6fven2Vc32Ve(bCfKbB1W2qfx1?0`g2ab0`0hfEf^gq0{2K0y8,0W0`fI2~e_1@e;5O0vfy0`0x3EbU0`cW0W0+edd70`0y8wgq0Bf?feehd}ek2e2Sdp1?fl0;0x0J9yeeff1V1X3B1|1*1,1.5n5b5939d$d~446A5B7ubm5`dR3O5Lb_b{c5b~3)d4c2d7c6hc7vc8dOc@9Eef179(ch8Cc^cPdibGcNh56P9dbzbBf)dXdPbHhDa+hB9ZhN6(8NgScYbWdZb@c_craUc-04b)cRb+hu5^7X0y0C1603fye:1Cflh@f}9@fPeAf_eZgsbb3Ka*b^dp6WbYc`dLaF8YhCcU6Si5hVho6#b-a+6~6ri7b=cBdNhE6!dQb*dnbR7r6 2EhKdkhXi2dg9)0/2rindz7Xh$52dfcgb5166CiHc{7AiG6Ec{6*c)h#dCh(dccSb,b3iO8Bif5Tindyi!4Jb-hwiPhyipil7tihith)9M04i-5Ui}bHiIiJhS9dcwc/i?iEcPiVa^c+hZ0Bj773iLjch,a3a5i`iximj4hR9)j2bWj6aU8Nbijbi*9%ikiSi9a.16i:c{jmjEhOibhQid7J7L7NjyiXi8bfa}jxa1dF04dHdJipdi06j-j%h8hoha9Chec~d0hhf9d5c3c5d9hobriu6`75hu06i@3B7ZhzcajQaCjvbg7IhHcK2vcMdahPkdjShUjVj4c#jI2oiYjk5Wh$i$hrb0h+dA1`h.h:h=gJfkh`gT5+erf2h f7i1hvjdj!7KdqbUiIj+kcbOke7QdokVdrjWcfb.jejsi|kt63jYhYhAk!hLk$cHiw5*iykjkrijb^jfkYjX040B7ujNk,k73%6AiRiWk;6}jHjZdwiZjMi#jDlbkTi,k)kXl6jji;dDjElch65Mka8Bi{5.judaj#k211iil60)kwk%j9iAkBjnk-a}l4lvlP3BlaiNjFjpcjlhc|6ok/lGlK7vk{dMlJi k3j5lNlZah7IjCj4k5c=i+dMlXl*6*jLl*l#c;lrdMkmk#jSj2lSi(iCjh98ioiT6blti.j$a3j)0vdKlkmc8Yj-j.b^0c0g0.0k0d0UmD0Dl5l*5Y0%dEj87I7`8Ql ip8ebC9^l/5Y0lmO738N8P0Omhh*ip8)8+jgbGm!mrm$9d9flpmwaQg39=9ym/9Zm;k,cu6S9Wm_k@a}0;9wfGm aCn1l$n301ajn6ctb^dUaz9Anemajom?7Ia!njmka}a?0zncbOnpiDnrkf6Sl~mYanmnhf3*d2hjfaj}d8j4nCkSnElQcvm*isi)l*7Aj^d10Whic0j|hmno4gdk0m3!54lB04j:l/j=k0hebT5QdHlunIaDl/iUl-nAhL76m=k^mKm`9uj16dkRbGhqir6HlFo7dkdenqkD5yiQ6Djgorl+mdk`mfmpbVl1l6m(bq6?046^j4ojiko6htl29)f~kRowa/nkiFoNlHk0cCi%b+l;bx9dmghWoPcPlD3%oUnw8BmCmEmGmI9Ao%oeoRaToDlqnVhslNipk_dkoLdhp5ddo,kbo`oAjUoCo2mjoTjKl{44m9nDow6Amtmvn7p2o2o{iv7Inmg=nYl^mj180Xh4d(d`5dpE0;0?0^0u04.

  1. on pourrait aussi représenter des nombres relatifs allant de -128 à 127 mais ce n'est pas le choix fait ici. 

  2. ce code ajoute la valeur d'une case à sa voisine de droite. La case copiée est vidée lors de l'exécution.