Aller au contenu

Plus longues sous-suites communes

Introduction à la programmation dynamique⚓︎

La programmation dynamique est une méthode algorithmique pour résoudre des problèmes d'optimisation. Le concept a été introduit au début des années 1950 par Richard Bellman.

Comme dans la méthode diviser pour régner, la programmation dynamique consiste à résoudre un problème en le décomposant en sous-problèmes. cependant, ici, ils ne sont pas forcément indépendants.

Ensuite, la programmation dynamique permet de résoudre les sous-problèmes, des plus petits aux plus grands en stockant les résultats intermédiaires (technique de mémoisation).

Voici un exemple avec la mesure de proximité de deux chaînes de caractères.⚓︎

Considérons les deux « textes » "LAPIN" et "CAPRIN".

À quel point sont-ils proches ?

Pour répondre à cette question, on peut se demander quelle est la plus longue sous-suite commune à ces deux textes.

Définition

On appelle sous-suite d'une chaîne de caractères, une chaîne produite en enlevant zéro, un ou plusieurs caractères.

Par exemple, "AN" est une sous-suite de "LAPIN".

"AN' est aussi une sous-suite commune à "LAPIN" et "CAPRIN".

Dans certains cas, il peut y avoir plusieurs sous-suites communes de longueurs identiques. Par exemple les chaînes "abc" et "bac" admettent deux sous-suites communes de longueur 2 : "ac" et "bc".

On va donc plutôt calculer la longueur de la plus longue sous-suite commune aux deux textes.

La comparaison de "LAPIN" et "CAPRIN" donne ceci (sur fond vert les caractères "identiques", sur fond rouge les "différents") :

LAPIN

CAPRIN

La plus longue sous-suite commune est donc "APIN". Elle est de longueur 4.

Écrire la fonction lplssc (pour longueur plus longue sous-suite commune) qui prend en argument les deux textes à comparer (texte_a et texte_b) et renvoie la longueur de la plus longue sous-suite commune.

On propose deux versions de cette fonction : une version récursive utilisant la mémoïsation et une itérative.

Ces deux méthodes permettent deux approches de la programmation dynamique : une qui construit la solution en partant des problèmes simples et en les combinant (bottom up), et une autre qui part du problème initial, découpé en sous problèmes, eux mêmes découpés par des les appels récursifs, jusqu'au cas de base (c'est la technique top down).

Exemples
1
2
3
4
5
6
>>> lplssc("LAPIN", "CAPRIN")
4
>>> lplssc("abcd", "abcde")
4
>>> lplssc("aBaBaBaB", "aaa")
3
Aide

Une approche consiste à déterminer les longueurs des plus longues sous-suites communes de toutes les versions de chaque texte : la version à 0 caractère, la version à 1 caractère, etc. Il y a (1 + len(texte_a)) × (1 + len(texte_b)) cas à envisager.

En prenant encore une fois texte_a = "LAPIN" et texte_b = "CAPRIN", les différents cas envisagés apparaissent dans le tableau ci-dessous. On trouve dans chaque case la longueur de la plus longue sous-suite commune à chaque texte s'il s'arrêtait au caractère indiqué en début de ligne ou de colonne.

Ainsi, le 1 au bout de la double flèche est la longueur de la plus longue sous-suite commune aux textes "LA" et "CAPRI".

Tableau de longueurs

On constate que :

  • la première colonne et la première ligne du tableau ne contiennent que des 0. C'est en effet la longueur de la plus longue sous-suite commune dans le cas où l'un des textes est vide ;

  • si les derniers caractères considérés sont identiques, ce caractère commun fait partie de la sous-suite commune. On peut le supprimer et ajouter 1 au résultat de la case au dessus à gauche (flèche en diagonale);

  • si les derniers caractères considérés diffèrent, l'un des deux caractères (ou les deux) ne fait pas partie de la sous-suite commune. On compare les valeurs des cases de gauche et du dessus (flèches horizontale et verticale).

Version récursive

Cette fonction fait appel à la fonction récursive lplssc_rec qui prend en paramètres le nombre de caractères de chaque texte à comparer taille_a et taille_b. Cette fonction renvoie la longueur de la plus longue sous-suite commune aux taille_a premiers caractères de texte_a et aux taille_b premiers caractères de texte_b.

Par exemple, avec texte_a = "LAPIN" et texte_b = "CAPRIN", l'appel lplssc_rec(2, 5) renvoie la longueur de la plus longue sous-suite commune à "LA" et "CAPRI".

On gardera trace des résultats intermédiaires dans un dictionnaire longueurs qui, à chaque couple (taille_a, taille_b), associe la longueur de la plus longue sous-suite commune.

La fonction étant récursive, on débutera par l'appel prenant en compte tous les caractères de chaque texte.

###(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 : 5/5

.128013ita;,EnD2R7+14 fj08}eloï?rO=[à]/mC3dv{.S5éwbcyq:-up)_9hxQPès6(gk050K0v0c0d0b0w0,0p0T0w0d0,0,0C010c0b0Z010406050,0Y0H0H0d0A0U040O0x0w0Y140x0h0p020d0H0Z0e0p0k0v1e0A0V0Y0v0,050G1b1d1f1h190Z04051M1F1P0G1M190K0b0L0|0~10120~0h0/0Y0d0/0v0X0Z0U0c0%1o0p0%0b0/0%0w1^0%0c17050@0S0w0v1Y0 11011@1_1{1_0c21231 0c0A1N1:0|1k0,0Z0d0h120j01251!010q0_0v0h1s0v1 2n2p2u272x232A0H2C040a0p0*0A0x0Z0x0,0b1n1p0=2l0A0A0v0T2X1F2E0h1N0G1:2-2h2j2i200K2G1#0b0h2z2U1 1V1X0}262`2|0h0x301 0Z2$1N2+2-3d1a2o1p322v360A1e0w1 0d1?2$0q12030#0#0T370v1{350x0X0n3E170p0n1F0d3e3h183g2F3j273l3n3p3r0v3t013v3x3z3B2}3E0X2s040p0j3K3M2p3O2+2_013T0d3o1N3q0%3s3u3w3y0=3%363)0J3H0J3/2*3N193?3R123_3{053}3 3Z413$2{3(3F0o3H0o4a1G4c3P3i1Z3S0x3m3`3V3~3X403#434p453F0P3H0P4v3d4d3h3@4h4F4l3!423A4L3D3F0-3H0-4R4x4e4A4g4C3U3|3W3Y4Z4o3C3)0l3H0l4,3;4T3Q4/3^4;4E4?4G4^4n4K4{3F0t3H0t502,524z33554D4i4k4H4m4J4#5d0X0$3H0$5i3=4U4f5n4=4j4@4I4!444%3E0s170n0s5A5k4V565p5H5s5J4$3)0n0n5O3J0G3L4b514y5T5o4X5r4_5c4q3E3+0n3.5)3:5j5-5D4W584Y5b5u5@0n4704675R5 54615G595I4`664s694u5|5+5~4.5m6e5q5a5t5K5!4O694Q6n4w3;1Q3b1F302:0K2j2^5D4!2 1W1N3a0v3c3N6o1N4!6T2F0b0K123w2+5!3V6!6$6v5Z3F5$0p2K0v6,5Y5v5$2-5*6q2v0:170=0q6V6c5m0R3H736}3S0q170w0Z0`0,0T785C5416040.7i536r170c0v0(7s0#0d7o5l2v7l0f6V0p743k7r7t7v0S7y3@7l0!0W6V196C2,5-6+016%3h3)3+5G7V646w3F2s6;2B6@6i4M3*1 5|0p7?7E79126 04717L5D763,7~6d7b047d7f0T0#2$7h7S6Y7z277l7n8c7F3S7r0^0w237w825m7B7D8j4g8l0_8o7K8i7_017N7P8c7R3f3?7$0#6(3F687#6#7W6-5v477+2L7-5?7/8N7=7@8#8u017{0b728c7^7j7q040@8x0v8p8,8%0x170C0C8t8B0H0b175Q8^8B0x804C8~8.7G8:8m8y997p2v8`048|9f8e1290928q7A178E4S7L8J8L0X6k8O8W657/4s8U6?8Q6^5@9z8!8#9M8-9g277{2$0c0Y0A0h9l3@9o04939u8A4U9w7Y4N6*8P7%6.0X4O9F9B7(9:7;3L9N7?8%8)8+3d9O9m8C178h8H9a8k9c8=8@a69P128s94a78va98n8?8zaca27N9X5D9617360caq54as042{aw8/0w1o1(0v9U1E9%ada3049t4xaJ1p9)2p3)4)4?8J9I7/4)9=9H7.5LaU3/9{9M9}178*aB9b7s7u8?7xaP7M170D9qa88;akab3Na13@9i0Xa/279Z5(ana_040Fb6129i9kagaK0h7Ha=0#am6U8B7la{a^608wa bo3;b2ar17b5bia2b8a|ae170FaN5,a^aR0h4|9,9?9/4}a!9.5v4}6{3,a*9{8%bk85aE1CaHbGaL0Da5bpah3^bv8oa@ba5Dafa0b$b?alb,7NbdbDb38{be01bFc3bA040mc6b%8610888ac0a4b,b%a~b@c6b4c6c8b_7k177Cc96db~bncpbBcr9169cj040!7Q9v9-8K9*0X5faVcLaX5L5fbU8R5@cPa)b!9|8B7{3A0,0vcGbK5~bMcL9x5xcQbR5v5xcVcS3)c;cZc!8$8Bceb)aG0AaIct8ra`b/6Dd0czb^b:aKb{b1b}aj9ebtcucHc2b|95c5cx6r0S171e0(cGd9c-babN5!5Nc=a#8X5L5P2t6=c?66dEc}c~9Ndicf7g892%dycldccB04bCdpb;csdeaocvcdczbx7Tbq170!cwd%bj7c7ecgdV8bd69r7mdYdja?cGd@dhdbe3cAds9hcCebb7cEb9d*bbcI8FcK6,9x5#bQdG9CdI6:dLer9@epbYdQc b;apelc.encN5`eqbV667*eveK7/eIezb#c$179S9U9WeeaiaD1%b*d4cGb.e2cne4dld704e6bydie+ead 8fd=doaOdBc/eH8N3qaWa$5!8TeNcWeP8Z3L8GeidC6/9zf1cRf3fedK7,ew9/0n9K9`7@dSd2b+eY01bgc67l0M0ucJeF8Qeo6y9Afm6_9;f6c`6/fG9Lbz549R0?eWd-85d{dUcie-e0dz8d4Vdu852zdXf!a}7Ie,e^bHcHe:2,fQdt7cf+f-f=f$e=f/e@eib`d=ek9$3f0G6X6E6S6G6P1F0c6Jgf2?2.0d22gc0G6H1Lf%5D2$0H0#0q0d0:8?0%681x1z1B1D0pc,2-1T1O040i2p0{0~0p0q1o2(0b1=3a2{0T153`241=3y1d2z0T242o0A0|0A0Q0vg-230p1VgT1o2A0b2$7E6Xe!aFfu6X0p2{2W0bg!2L0h0c0p0L6!241B0b0p0Zg;2L2d0A3q2Z051y040H0Q0H0x0yc)0A1Fhr0N060B1p1$g*0p2z1b2W24230{0d0Zhj0`0pg/0TaH8*0{2z0pc)g@1y2p0K2phbgEakhI0,hbgPh0e$h$0pgP7e0YgOd2h!0xh{0XhK7s2l1d0Y2|h!hh0w00g$1o2V0K0+2$060ch 7sgOgF23hmgF2Z0T0%0dgE0pa;i30Wg~3zfW87d}0.2J0.ixa?d?h^2ziHg10S0!ekh30z1Q3O1M0I0xg(h^3q0,h 0,0XgR0hg_1p1DhbhUhW0L0v0fh40wh.hb0S1=2Z0K0Q0S1mg;hi1f0pi60|0 h@0S0 0vhC0I00i.h4gYiLj80{h h^00j70=0{0=0Y0(iwf/0{i73yha0b2zhb0d0YhV3i1f0d2(igjd0pgM0h0{hH0T0 i@1=2$0h0L0xjCg@g|2%7sh9hb054!3@1$1(1*1,1.1?1|2b1}2Dd(cE9#6Ug9iB0NiUgqhEhc0Q0A8*j#hJ0YhL0pivg?jThO0p0Q0c0Qiwhn2Wkmjn360h0N2Ph g-g*gP1=h#0=1e0h2Z2Vi!1Ykmj,iBiH9da?i@e?iP1F6X060hjgh/j40{3a0Qc)ha24h)jQjkg^2Xg{g}kK0=b(e#d3aI6Xk21SiV1ihh0TkWh:24khi@0_gQjFhb2h0^7skx0?i3g%g,0^i$1p8EgJ0Y0w3O1{04kGhNh$9VjCd4j8hnjL2$jRid6!k7k#h~hah40=jBgE0,jV1p2o1024jFjvjTly0cjMkZhU0QlJ0chYh:ib1p0d0rik24k:l254j/1)1+1-0Uj@2a1|1~gr54d)6Dk0k;0pjFhTk#lm0@hb0e1Flp19lplrgFlUjKlWlAj$0q0qjMhalNkj9T1VhMiqaGlTj9k!gY0,lFg,jo0Qks0T0Qkuk57ejKk(gNk+0bi,k.mvm61b0wm9jkh`0{0/hnkEk`md1Flmk|0)1Ci_ivi$2WjkkhhIjY0b0,1*0Qi@gP0Lg!9Ui`h41dl!h7j)jDh!ij0T0:g:g@mPg?k,gU0hmTiAk;h=k@kSk1k3gK0g2Yg;0hlvh^jC0YmrjXjZj#n0n2g-kfl)hcjClH0K002{mC2$g-k)imj$mS0^g}jnkyg?hgmslag@0Q0r0Ehig/k$7sk`gJgo0?8m0,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 : 5/5

.128013ita;,EnD2R7+14 fj08}eloï?rO=[à]/mC3dv{.S5éwbcyq:-up)_9hxQPès6(gk050K0v0c0d0b0w0,0p0T0w0d0,0,0C010c0b0Z010406050,0Y0H0H0d0A0U040O0x0w0Y140x0h0p020d0H0Z0e0p0k0v1e0A0V0Y0v0,050G1b1d1f1h190Z04051M1F1P0G1M190K0b0L0|0~10120~0h0/0Y0d0/0v0X0Z0U0c0%1o0p0%0b0/0%0w1^0%0c17050@0S0w0v1Y0 11011@1_1{1_0c21231 0c0A1N1:0|1k0,0Z0d0h120j01251!010q0_0v0h1s0v1 2n2p2u272x232A0H2C040a0p0*0A0x0Z0x0,0b1n1p0=2l0A0A0v0T2X1F2E0h1N0G1:2-2h2j2i200K2G1#0b0h2z2U1 1V1X0}262`2|0h0x301 0Z2$1N2+2-3d1a2o1p322v360A1e0w1 0d1?2$0q12030#0#0T370v1{350x0X0j0X0n170p0n1F0d3e3h183g2F3j273l3n3p3r0v3t013v3x3z3B2}3E3E3I0j3L3N2p3P2+2_013U0d3o1N3q0%3s3u3w3y0=3(363*0J3I0J3.2*3O193=3S123^3`053|3~3!403%2{3)3F0o3I0o491G4b3Q3i1Z3T0x3m3_3W3}3Y3 3$424o443F0P3I0P4u3d4c3h3?4g4E4k3#413A4K3D3F0-3I0-4Q4w4d4z4f4B3V3{3X3Z4Y4n3C3*0l3I0l4+3:4S3R4.3@4:4D4=4F4@4m4J4`3F0t3I0t4 2,514y33544C4h4j4G4l4I4!5c0X0$3I0$5h3;4T4e5m4;4i4?4H4Z434$3G0s170n0s5z5j4U555o5G5r5I4#3*0n3H045!5Q4x5S5n4W5q4^5b4p3G2s5$3-0G3M4a505)5C4V574X5a5t5:0n465$485^3/5i5|535~5F585H4_634r5$4t685`6a4-5l6d5p595s5J5Z4N5$4P6m4v3:1Q3b1F302:0K2j2^5C4Z2 1W1N3a0v3c3O6n1N4Z6S2F0b0K123w2+5Z3W6Z6#6u5Y3F3H0p2K0v6+5X5u5#496p2v0:170=0q6U6b5l0R3I716{3T0q170w0Z0`0,0T765B5316040.7g526q170c0v0(7q0#0d7m5k2v7j0f6U0p723k7p7r7t0S7w3?7j0!0W6U196B2,5)6*016$3h3*5=5F7T616v3F2s6:2B6?6h4L3+2-3M0p7;7C77126}046 7J5C74047C7Q6X7x787a7c100T0#2$7f817D277j7l8c7@3@7p0^0w237u7|7i177A817?7h7o040@0_8n7I8h8v7y177M7O7J7!0#6%3F657Z6!7U6,5u467)2L7+5/7-8N687=8#8u7n6|170b708t8d4f8k8z0v8o8-8i0x170C0C7B8.010H0b175P8@8D270x7~4B8}8i0h8:8m8=8B3d8%83128_048{9a951290928p5l7j7N817P3f3=8J8L0X6j8O8W627-4r8U6=8Q6@5:9E8!8$9R8~7_2$0c0Y0A0h9o8(279r04934R8I8P7V2p3*6x9F9M7,5K4N9K9G7$0X9:9Q9S8i7_8+9!9j018f9t7E8x8l8n7v8C9#127za34U9d8Aa78e8Fah5C9717360cao53aq042{au8w0w1o1(0v9X1Eada49v8HaH0p9B7W4%6)9,8R5:4(9_9=8X5K4(7/7 9R8$9T8*8,9h8~9c8x7G8=ac9z9pa5170Dal8/a98;8?a+8^170Xaz2v9%3KaL5C7j0Fb3968`8|94ae8ja.7s9fa`a@04a_b76cajbkbfa49lb2bt3?b5blb99w9*aLaN9.3F4|4=8J9N7-4|aV7#6-0XbI3.a$bU9iai04aB1%1CaFbAa^8ga=bga-8y9ea~6T8iagbx5}br0#9gb:a?7Lbab?av8`bb9q915$c2019l0mc6a-7b7d888ab%7kblb,aaa:c6bvc6bzbp9u8rcab^b`3:bWapb1coc4b6b*aIan9x9+6+9C5ebJaRbL5K5ebOaS7-cKbTbV7;a(043A0,0vcgbC4wbEaR9C5wcL9`bQ5wcQcN3*c,cUcV8#a,7aaCb#0AaGcD7Kb(cib^a;b{bgb=a a?cja}cv7Rb;8Fb~dabg9lbedja40h0S171e0(cgb)c(d1bF0h5Z5Mc-aW9H5K5O2t6;c.6^dBc^c_9 db85cd892%dud4a|b.d6cw8~cnb 5lcpd1b8csd$a8b-akcq8E040!8sdnbXcc87dS8bd)8qchd:3Td5cgd@3OcxbqdWd/d^cy04bweb53d(d7cEd=aKdxc*aO3G6_3qbK9?5Z6/dIdD9{5!1 9~dNe7crekcGc)cIeo0n7YercMet6.7(ewbP6^7YeBc`a0179V9X9Zd,e2bYc}aEc cg0Ddv6C9be3e1afd+ef8wd.bsd~eE0!didweiaMenbG3G8NeMdJ638TeRcRdF8Z3M9yf1dy5Z9Ef7exbQ0n9Jfbc=6.9P7:7=c{e(b!e*d0e6d!c1e$e?040M0uelfhf3dz6.9:fleS639^fqeO3G9}fucWeX04eZ9YctbY867ed|dUe=3@dqbY2zf,e|d-a/b/e/b|8Fe5dZ9bf/2Jf=f1b@bi7Hcg0!0!fJ6C0G6W6D6R6F6O1F0c6Igi2?2.0d22gf0G6G1L823?2$0H0#0q0d0:8=0%651x1z1B1D0pc%gb1T1O040i2p0{0~0p0q1o2(0b1=3a2{0T153_241=3y1d2z0T242o0A0|0A0Q0vg:230p1VgW1o2A0b2$7C6WbZaDb$gc3z7 2{2W0bg%2L0h0c0p0L6Z241B0b0p0Zg@2L2d0A3q2Z051y040H0Q0H0x0yc!0A1Fhv0N060B1p1$g-0p2z1b2W24230{0d0Zhn0`0pg=0TaF8+0{2z0pc!g`1y2p0K2phfgH9ehM0,hfgSh3c~h*0pgS7c0YgRe)h(0xh 0XhO7q2l1d0Y2|h(hl0w00g)1o2V0K0+2$060ci37qgRgI23hqgI2Z0T0%0dgH0p7qbjgJh1h7d`f*8a0.2J0.iB7t0dd?h|2ziLf^0Sg81F6W0p0z1Q3P1M0I0xg+h|3q0,i30,0XgU0hg|1p1DhfhYh!0L0v0faM0wh=hf0S1=2Z0K0Q0S1mg@hm1f0pia0|0 h{0S0 0vhG0I00i@aMg#iQje0{i3h|00jd0=0{0=0Y0(iAa/0{ib3yhe0b2zhf0d0YhZ3i1f0d2(ikjj0pgP0h0{hL0T0 i}1=2$0h0L0xjIg`g 2%7qhdhf054Z3?1$1(1*1,1.1?1|2b1}2Da?9%9)6Th60=040Ni!gthIhg0Q0A8+j+hN0YhP0pizg_jZhS0p0Q0c0QiAhr2Wktjt360h0N2Pi3g:g-gS1=h)0=1e0h2Z2Vi*1Yktj=h7iLck7ui}e`b_g9k66R060hjmh?ja0{3a0Qc!he24h-jWjqg{2Xg~h0kRk7h_fziWh7k91Si#1ihl0Tk(h@24koi}0_gTjLhf2h0^7qkE0?i7g*g/0^i,1p9wgM0Y0w3P1{04kNhRh*9YjIc jehrjR2$jXih6Zkek-i2hef2jJ0bgH0,j#1p2o1024jLjBjZlF0cjSk+hY0Q0=heh$h@if1p0d0rio24k{l953j^1)1+1-0Uj}2a1|1~gu5CehgbiXjLhXk-lt0@hf0e1Flw19lwlygIl#jQl%lHj,0q0qjShelUkq9W1VhQiuaEl!jfk,g#0,lMg/ju0Qkz0T0QkBkc7cjQk:gQk?0bi=k_mAmb1b0wmejqh~0{0/hrkLl1mi1Fltl30)1Ci izi,2WjqkohMj(0b0,1*0Qi}gS0Lg%9Xj0aM1dl+hbj/jJh(in0T0:g?g`mUg_k@gX0hmYiEk|e)h56Wl1gM1M0g2Yg@0hlCh|jI0Ymwj%j)j+n5n7g:kml:hgjIlO0K002{mH2$g:k;iqj,mX0^h0jtkFg_hkmxlhg`0Q0r0Ehmg=k.7qnx3Pgr0?8l0,04.
Version itérative

Dans cette version itérative on détermine là encore les longueurs des plus longues sous-suites communes de toutes les versions de chaque texte.

On peut toutefois remarquer que les deux formules de récurrences (derniers caractères identiques ou différents) ne font intervenir que deux lignes à la fois. On peut donc compléter le tableau ligne par ligne en partant de la première et en ne gardant trace que de la dernière ligne complétée.

Une seule ligne est nécessaire

###(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 : 5/5

.128013ita;,n2Rê7+14L f08elorO=[à]/mC3dv.S5éwbcyq:-up)_9hxPès6(gk050G0t0c0d0b0u0$0p0O0u0d0$0$0y010c0b0U010406050$0T0D0D0d0w0P040J0v0u0T0~0v0g0p020d0D0U0e0p0i0t180w0Q0T0t0$050C1517191b130U04051G1z1J0C1G130G0b0H0?0^0`0|0^0g0)0T0d0)0t0S0U0P0c0Y1i0p0Y0b0)0Y0u1/0Y0c11050.0N0u0t1S0_0{011.1:1=1:0c1{1}1_0c0w1H1*0?1e0$0U0d0g0|0h011 1U010q0:0t0g1m0t1_2h2j2o212r1}2u0D2w040a0p0!0w0v0U0v0$0b1h1j0,2f0w0w0t0O2R1z2y0g1H0C1*2%2b2d2c1`0G2A1V0b0g2t2O1_1P1R0@202;2?0g0v2`1_0U2W1H2#2%37142i1j2|2p300w180u1_0d1-2W0q0|030W0W0O310t1=2 0v0S0F0S0m110p0m1z0d383b123a2z3d213f3h3j3l0t3n013p3r3t3v2@3y0S2m040p0h3F3H2j3J2#2:013O0d3i1H3k0Y3m3o3q3s0,3Y303!0F3C0F3*2!3I133.3M0|3;3?053^3`3U3|3X2=3Z3z0n3C0n451A473K3c1T3N0v3g3=3Q3_3S3{3W3~4k403z0K3C0K4q37483b3/4c4A4g3V3}3u4G3x3z0%3C0%4M4s494v4b4x3P3@3R3T4U4j3w3!0k3C0k4%3,4O3L4*3:4,4z4.4B4:4i4F4?3z0s3C0s4{2$4}4u2}504y4d4f4C4h4E4W580S0X3C0X5d3-4P4a5i4-4e4/4D4V3 4Y3A0r110m0r5v5f4Q515k5C5n5E4X3!0m3B045W5v1K351z2`2*0G2d2/5y4V2_1Q1H340t363I463,054V5@2z0b0G0|3q2#5V3Q5 615o5F640p2E0t675T5q5X454)5h0*110,0q5_2$4t3/0M3C6p5}5g3e0q110u0U0;0$0O6v6r5y10040(6G6j3e110c0t0Z6Q0W0d6M5x4 6J0f6v0p6H4 0g6P6R6T0N6W4~5h6J0V0R6v134r5`3.6601623b3!3$5B6|565p4l3#2n6c6e4=76710C3G0p7g6$6N3N6A1i1Y0t0T0w1y6_2$7i6X5h0v110y6#6%6:110z6.6x210D0b115L7s3%7B2p6l040q4x7A7j4b110W7U7v2p0v6t042=7Z6/3e0N110w2j1#7F3/6J6L7M7O3N7-042D7=6I117^397V3:6*6S0t6U7 6Y110V7*7G0|7x040l8e3/7I5J8a7C040V0B6@7=730W633z424.8v6f76426b2v7a578D1_7e3%7h7`0|7Q7S0w8k5y6)040.0:1}0W6-7M7u7+217$117)8$8O3:7|7/1X0t8o2p7@8@7H7J5Y8`0|6Z8T6(7|7~7_848_957!7k8W6+888#83998 8c917w118j8-848m8}988(9h8q6?7M6^9f5~606}8w6 4m659A74699E8F2F8H754H0S4n2%7f7h9T8.8V6Q1n9j7#7y9Z216J7E9r8f019p7L378%9+8Q7T9n9g85047Y9@9s018*7(0g9$4b8:7:8?9*7?818~8/6A2taa979y9+9W9c89a7808qa29~9lao9p3Eal8b8q8s9w8u9G9C2j3!4J8AaA8C9O4J9K6d9BaH5GaE3*9T9U849=8S9|ah6P0/0u8Z6VaW3/9 8,9/9Va48=aea9au5hasa/046!a%8U93ada;8^a:ag4Q866Ta$b1am8da`4 8h9ma+9o8|atb6av6=8ta78v8x0S4!aF9M9Ibo788GaM7b9ObpaQaRbB8.7Q0b6ob95hai87akbh8p9)bM6O8WaZa#ao8h0Sarbfa@axbd9^8h0y7zbHbQ6QbK9e5^967Daa9WbS9dbU11bWb*8{8na~9%110B9v4Naz67bn4^bqbw8I9O4^aKbr5U3zc8bAbBck9:b29b9Yb 9tbOb/9^b?8Y88b5ct9}6Jb!3Icm5yb%bXb~b#9}bbao8V0u7m1w7p7rbPc004cs6`cuaYcwbLcD8.bVcH9qcT9tcC4|c59Bbn5ac99Hcg0S5aceca9N5Gc=cjclcE4 7Q3u0$a6c+016Jc34sblaAbn5sc?68c^5sc{c@5qdgd0d18N84aicpd89(b=cZa!cxbZb_04b)cJah7|180Za@82czaXco0Ua@cW6qdsdybTb|8gb`c)bgdMa8040Ba_dFcncO1XcQ7qdQdxbRc!cycXcAc1b8c4ddc69D5H9Fcf6g5Idldie38K9SbCdT7}cP7od/dWapdDcM6*dudcb1bmd 5We1c|bseqe5aN5V6h8LaS9^7Q2W0c7pa1egcNedcRd:cqab7}a}dvb0d#8Ub3dAeM6;c-5e6G0C5|5#5?5%5:1z0c5*e+2-2(0d1|e(0C5(1F6w3/2W0D0W0q0d0*880Y8z1r1t1v1x0pdb5`1M3J1G0E0-6Q0p7S0g2Y0b1,1x0c0p2Q0L7/0~0H1~0-2f0g0$2b0T2Q1~0d1g0v7p0p0G000T2?0p0NfH0@1~5{3t3/1W1Y1!1$1(1-1?251@2xeB118Re!5|0I1Kfd040o1~280tfF0pfA0v0O0*2jfp1}0=d,7ncRfJf81P0q0qfs2t6Q0=0$fH0$0S15fD0=3s17fMg80t0H7/2Q0p0d0H0v0b0w6$4VfV7:1Z1#1%0Pf#241?1^e`5ya?egcLeHa|eGeQ6Kd;b,b4a@d{5^e#3t3%3sd,2?0=fxfT2T5yfWgFfZgI231;gLf)9}gPd*cFaqgSacgUeSavdLd^dNgYb^eW9i7_g%0,3%25g,0I060x3c1ifA0dfh0g0L2j0Dgyfz0pf70pg2fi4,0ThB2T0w0L0O7p2Wfk1~fNfjfp0d0U0Ud5hy0T000Ag70=0H3=ee0=0b0`1w0=2T0^0p0D0j2FhA1/fNfHg7hA3k34hI0L0,0g6Qf/fce_hm0phT1gfJ1i0Of{1~3si1gd0tgAfK1g0:h)iig70T0Z0pf^fFir2Tg/ie4 g=fYgHgJg`26g|9+g~g$5|h?0)2?i31N1If=h|e|0b0#2WiLfN0G0Tise;1}f`fxh.5=7IiVie1e1ifNfNif0~2t2 fphz0,0=ixgDd-iBf!g_f%gM8.9-f-g(iOf;0!fHgAgn6C0L6QgAhBfF2bf80O0_1x0f0p1,il1=d6hAf88R0DhEgq0phHhJ2V2t0O0tja6^0,8X0;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 : 5/5

.128013ita;,n2Rê7+14L f08elorO=[à]/mC3dv.S5éwbcyq:-up)_9hxPès6(gk050G0t0c0d0b0u0$0p0O0u0d0$0$0y010c0b0U010406050$0T0D0D0d0w0P040J0v0u0T0~0v0g0p020d0D0U0e0p0i0t180w0Q0T0t0$050C1517191b130U04051G1z1J0C1G130G0b0H0?0^0`0|0^0g0)0T0d0)0t0S0U0P0c0Y1i0p0Y0b0)0Y0u1/0Y0c11050.0N0u0t1S0_0{011.1:1=1:0c1{1}1_0c0w1H1*0?1e0$0U0d0g0|0h011 1U010q0:0t0g1m0t1_2h2j2o212r1}2u0D2w040a0p0!0w0v0U0v0$0b1h1j0,2f0w0w0t0O2R1z2y0g1H0C1*2%2b2d2c1`0G2A1V0b0g2t2O1_1P1R0@202;2?0g0v2`1_0U2W1H2#2%37142i1j2|2p300w180u1_0d1-2W0q0|030W0W0O310t1=2 0v0S0n0S0m110p0m1z0d383b123a2z3d213f3h3j3l0t3n013p3r3t3v2@3y0S2m040p0h3F3H2j3J2#2:013O0d3i1H3k0Y3m3o3q3s0,3Y303!0F3C0F3*2!3I133.3M0|3;3?053^3`3U3|3X2=3Z3z0n3C0n451A473K3c1T3N0v3g3=3Q3_3S3{3W3~4k403z0K3C0K4q37483b3/4c4A4g3V3}3u4G3x3z0%3C0%4M4s494v4b4x3P3@3R3T4U4j3w3!0k3C0k4%3,4O3L4*3:4,4z4.4B4:4i4F4?3z0s3C0s4{2$4}4u2}504y4d4f4C4h4E4W580S0X3C0X5d3-4P4a5i4-4e4/4D4V3 4Y3A0r110m0r5v5f4Q515k5C5n5E4X3!0m3B045W5v1K351z2`2*0G2d2/5y4V2_1Q1H340t363I463,054V5@2z0b0G0|3q2#5V3Q5 615o5F640p2E0t675T5q5X454)5h0*110,0q5_2$4t3/0M3C6p5}5g3e0q110u0U0;0$0O6v6r5y10040(6G6j3e110c0t0Z6Q0W0d6M5x4 6J0f6v0p6H4 0g6P6R6T0N6W4~5h6J0V0R6v134r5`3.6601623b3!3$5B6|565p4l3#2n6c6e4=76710C3G0p7g6$6N3N6A1i1Y0t0T0w1y6_2$7i6X5h0v110y6#6%6:110z6.6x210D0b115L7s3%7B2p6l040q4x7A7j4b110W7U7v2p0v6t042=7Z6/3e0N110w2j1#7F3/6J6L7M7O3N7-042D7=6I117^397V3:6*6S0t6U7 6Y110V7*7G0|7x040l8e3/7I5J8a7C040V0B6@7=730W633z424.8v6f76426b2v7a578D1_7e3%7h7`0|7Q7S0w8k5y6)040.0:1}0W6-7M7u7+217$117)8$8O3:7|7/1X0t8o2p7@8@7H7J5Y8`0|6Z8T6(7|7~7_848_957!7k8W6+888#83998 8c917w118j8-848m8}988(9h8q6?7M6^9f5~606}8w6 4m659A74699E8F2F8H754H3y8K7f7h9S8.8V6Q1n9j7#7y9Y216J7E9r8f019p7L378%9*8Q7T9n9g85047Y9?9s018*7(0g9#4b8:7:8?9)7?818~8/6A2ta9979y9*9V9c89a6808qa19}9lan9p3Eak8b8q8s9w8u9G9C2j3!4J8Aaz8C9O4J9K6d9BaG5GaD3*9S9T849;8S9{ag6P0/0u8Z6VaV3/9~8,9.9Ua38=ada8at5hara.046!a$8U93aca:8^a/af4Q866Ta#b0al8da_4 8h9ma*9o8|asb5au6=8ta68v8x0S4!aE9M9Ibn788GaL7b9OboaPaQbA8.7Q0b6ob85hah87ajbg8p9(bL6O8WaYa!an8h0Saqbea?awbc9@8h0y7zbGbP6QbJ9e5^967Da99VbR9dbT11bVb)8{8na}9$110B9v4Nay67bm4^bpbv8I9O4^aJbq5U3zc7bzbAcj9/b19b9Xb~9tbNb.9@b=8Y88b4cs9|6JbZ3Icl5yb$bWb}b!9|baan8V0u7m1w7p7rbOb 04cr6`ctaXcvbKcC8.bUcG9qcS9tcB4|c49Bbm5ac89Hcf0S5acdc99N5Gc;cickcD4 7Q3u0$a5c*016Jc24sbkazbm5sc=68c@5sc`c?5qdfc d08N84ahcod79%b;cYaZcwbYb^04b(cIag7|180Za?82cyaWcn0Ua?cV6qdrdxbSb{8gb_c(bfdLa7040Ba^dEcmcN1XcP7qdPdwbQcZcxcWczc0b7c3dcc59D5H9Fce6g5Idkdhe29Q8MbBdS7}cO7od.dVaodCcL6*dtdbb0bld~5We0c{brepe4aM5V6h8LaR9@7Q2W0c7pa0efcMeccQd/cpaa7}a|dua d!8Ub2dzeL6;c,5e6G0C5|5#5?5%5:1z0c5*e*2-2(0d1|e%0C5(1F6w3/2W0D0W0q0d0*880Y8z1r1t1v1x0pda5`1M3J1G0E0-6Q0p7S0g2Y0b1,1x0c0p2Q0L7/0~0H1~0-2f0g0$2b0T2Q1~0d1g0v7p0p0G000T2?0p0NfG0@1~5{3t3/1W1Y1!1$1(1-1?251@2xeA118ReZ5|0I1Kfc040o1~280tfE0pfz0v0O0*2jfo1}0=d+7ncQfIf71P0q0qfr2t6Q0=0$fG0$0S15fC0=3s17fLg70t0H7/2Q0p0d0H0v0b0w6$4VfU7:1Z1#1%0Pf!241?1^e_5ya=efcKeGa{eFeP6Kd:b+b3a?d`5^e!3t3%3sd+2?0=fwfS2T5yfVgEfYgH231;gKf(9|gOd)cEapgRabgTeRaudKd@dMgXb@eV9i7_g$0,3%25g+0I060x3c1ifz0dfg0g0L2j0Dgxfy0pf60pg1fh4,0ThA2T0w0L0O7p2Wfj1~fMfifo0d0U0Ud4hx0T000Ag60=0H3=ed0=0b0`1w0=2T0^0p0D0j2Fhz1/fMfGg6hz3k34hH0L0,0g6Qf.fbe^hl0phS1gfI1i0Of`1~3si0gc0tgzfJ1g0:h(ihg60T0Z0pf@fEiq2Tg.id4 g;fXgGgIg_26g{9*g}g#5|h=0)2?i21N1If;h{e{0b0#2WiKfM0G0Tire:1}f_fwh-5=7IiUid1e1ifMfMie0~2t2 fohy0,0=iwgCd,iAfZg^f$gL8.9,f,g%iNf:0!fGgzgm6C0L6QgzhAfE2bf70O0_1x0f0p1,ik1=d5hzf78R0DhDgp0phGhI2V2t0O0tj96^0,8X0;04.

Crédits: page modifiée d'après codex, de Nicolas Révéret et Franck Chambon.