diff --git a/content/pages/parenthesons.md b/content/pages/parenthesons.md new file mode 100644 index 0000000..fc86e39 --- /dev/null +++ b/content/pages/parenthesons.md @@ -0,0 +1,215 @@ +status: hidden +title: Python — Parenthésons +slug: eiRah1ch-parenthesons +robots: noindex + + +# Partie Ⅰ + + +Après Epitech Digital, et un doctorat en informatique vous rejoignez +une equipe chargée de concevoir le prochain langage de programmation à +la mode : le Morecambe. + +Dans l’equipe « ASV », « Age^WAnalyse Syntaxique et Validation », vous +travaillez sur le parenthésage des expressions : + +- `(a + b)` est valide. +- `)a + b(` n’est pas valide. +- `(a + (b + c))` est valide. +- `(a + (b + c)` n’est pas valide. +- `a * (b + c) + (d / 2)` est valide… + +Jusque-là ça va, mais Morecambe est un langage moderne, il ne s’arrête +pas aux mathématiques classiques, et permet d’exprimer de la logique +combinatoire, du lambda-calcul, de la sémantique dénotationnelle (en +convergence et en divergence), et j’en passe, ainsi : + +- `(λa ∘ λb)(3)` est valide, c’est une simple composition des + fonctions `a` et `b`, immédiatement appellée. +- `⍼((a∘b)(3))|⍼((c∘d)(12))` est valide, c’est le « Right Angle with + Downwards ZigZag Arrow » qui permet la dénotation (divergente, pour + le coup), le `|` ne servant qu’à chaîner, comme en bash, + naturellement. +- `[¬(a ⋀ b) ⋁ ¬(c ⋀ d)] ∀ a⍼((c∘d)(12)` n’est cependant **PAS** + valide, bien qu’[Augustus De + Morgan](https://fr.wikipedia.org/wiki/Lois_de_De_Morgan) aurait pu + la corriger en un coup de cuiller à pot. + +Votre première tâche sera donc d’écrire une fonction, en Python (il +faudra la réecrire en Morecambe une fois le compilateur Morecambe +fonctionnel, pour compiler Morecambe en Morecambe et boucler la +boucle, en attendant, on code en Python). Une fonction nommée +`is_correctly_balanced` qui prend en paramètre une chaîne de +caractères nommée `expression`, et qui renvoie `True` si l’expression +est correctement paremthéséee, et `False` dans le cas +contraire. + +L’équipe vous a préparé quelques tests unitaires et vous aurez la +bienveillance de les stocker dans le projet afin de pouvoir les +exécuter avec `pytest` : + +```python +def test_bare(): + assert is_correctly_balanced("") is True + assert is_correctly_balanced("()") is True + assert is_correctly_balanced("(((())))") is True + assert is_correctly_balanced("()()()()") is True + assert is_correctly_balanced("()(())()") is True + assert is_correctly_balanced(")(") is False + assert is_correctly_balanced("(((") is False + assert is_correctly_balanced("((()") is False + assert is_correctly_balanced("()))") is False + assert is_correctly_balanced("()()()(") is False + +def test_full(): + assert is_correctly_balanced("(a + b)") + assert not is_correctly_balanced(")a + b(") + assert is_correctly_balanced("(a + (b + c))") + assert not is_correctly_balanced("(a + (b + c)") + assert is_correctly_balanced("a * (b + c) + (d / 2)") + assert is_correctly_balanced("(λa ∘ λb)(3)") + assert is_correctly_balanced("⍼((a∘b)(3))|⍼((c∘d)(12))") + assert not is_correctly_balanced("[¬(a ⋀ b) ⋁ ¬(c ⋀ d)] ∀ a⍼((c∘d)(12)") +``` + +Dites, à quel point c’est frustrant si je vous dis que `((()))` écrit +à l’envers çax donne `)))(((` ? + + +# Partie Ⅱ + +En rédigant votre fonction vous remarquez un fait amusant : donné un +certain nombre de paires de parenthéses, il n’y a qu’un nombre fini de +possibilités pour les agencer. + +Vous ne pouvez donc vous retenir d’implementer une fonction pour tous les +lister ! + +Votre fonction doit s’appeler `gen_correctly_balanced_expressions` et +prendre un seul parametre `n` : le nombre de paires de +parenthéses. + +Elle doit renvoyer un iterable de tous les parenthésages possibles, +chaque parenthésage étant exprimé sous la forme d’une chaine de +caractères. Vous devinerez vite qu’il n’existe qu’une seule manière de +parenthéser une seule paire de parenthéses, puis vous découvrirez +qu’il existe +- deux manieres de parenthéser deux paires, +- 5 manieres d’en parenthéser trois, +- 14 d’en parenthéser 4, +- ... +- 4862 d’en parenthéser 9... + + +Voici par exemple les 14 parenthésages valides avec quatres paires de +parenthéses : + +- `(((())))` +- `((()()))` +- `(()(()))` +- `(()()())` +- `((())())` +- `()((()))` +- `()(()())` +- `()()(())` +- `()()()()` +- `()(())()` +- `(())(())` +- `(())()()` +- `((()))()` +- `(()())()` + +Vous utiliserez cette fonction pour tester votre première fonction +avec pytest, prouvant sa robustesse, et impressionant de fait votre +équipe. + + +# Partie Ⅲ + + +Il est maintenant tard, mais vous n’arrivez pas à décrocher de vos +parenthésages. Vous contemplez votre travail, vous jouez avec +`gen_correctly_balanced_expressions(5)`, +`gen_correctly_balanced_expressions(6)`… vous n’êtes plus très +productif à cette heure de la nuit, mais ces fonctions vous +distraient. Vous vous dites que ça pourraît être joli si on pouvait +remplacer les parenthéses par d’autres symboles… + +Vous ajoutez donc deux arguments optionnels à votre fonction : +`opening`, et `closing`, qui respectivement valent par defaut `"("`, +et `")"` afin de ne pas changer le comportement d’origine de votre +fonction. + +Et vous voilà parti à jouer avec votre nouvelle fonction : + +- `gen_correctly_balanced_expressions(4, "[", "]")` +- `gen_correctly_balanced_expressions(4, "<", ">")` +- `gen_correctly_balanced_expressions(4, "la", "li")` +- `gen_correctly_balanced_expressions(4, "Tum ", "Pak ")` +- `gen_correctly_balanced_expressions(4, "𝅗𝅥", "𝅘𝅥𝅮")` +- `gen_correctly_balanced_expressions(4, "Je suis en retard…", "en retard…")` + + +# Partie Ⅳ + +Il est vraiment tard cette fois, mais vous décidez de suivre le lapin +blanc jusqu’au fond du terrier. + +Et ça y est, vous testez enfin : + +`gen_correctly_balanced_expressions(5, "1", "0")` + +Du binaire… des nombres ! Et aucun ne commence par zéro !! Et ils +sont tous pairs ! Ça ne peut pas être une coïncidence… + +Vous rédigez alors une fonction `gen_balanced_sequence` qui prend en +paramètre `n`, le nombre de pairs de bits à utiliser, et qui renvoie +un iterable de nombres entiers ordonnés par ordre croissant : les +nombres genérés par votre expérience précédente. Ces séquences sont +interessantes, mais trop courtes : + +```text +2 +``` + +puis : + +```text +10 +12 +``` + +puis : + +```text +42 +44 +50 +52 +56 +``` + +… + +Vous décidez alors de rédiger une fonction `gen_balanced_sequences` +(notez le pluriel) qui ne prend pas de paramètre, mais qui renvoie un +itérable infini (ou qui affiche et ne renvoie rien, à votre guise), des nombres +genérés par la fonction précédente, vous obtenez alors : + +```text +2 +10 +12 +42 +44 +50 +52 +56 +170 +172 +… +``` + +Vous contemplez la séquence ainsi générée, et vous hésitez entre aller +dormir et vous lancer dans une thèse pour étudier cette séquence…