Code source de ensae_teaching_cs.special.hermionne_classes

# -*- coding: utf-8 -*-
"""
Implémentation de la résolution de l'énigme d'Hermionne (Harry Potter tome 1)
avec des classes.
`logique <https://fr.wikipedia.org/wiki/R%C3%A8gle_de_r%C3%A9solution>`_.


:githublink:`%|py|8`
"""


[docs]class Case: """ L'énigme d'Hermionne repose sur 7 cases disposées en ligne. Cette classe définit une case. :githublink:`%|py|14` """ contenu_case = ["poison", "vin", "reculer", "avancer"]
[docs] def __init__(self, contenu): """ constructeur :githublink:`%|py|20` """ self.contenu = Case.contenu_case.index(contenu)
[docs] def __str__(self): """ affiche le contenu :githublink:`%|py|26` """ return Case.contenu_case[self.contenu]
[docs]class Regle: """ L'énigme repose sur des règles. Chaque règle hérite de cette classe et implémente la méthode *correcte* qui vérifie si la règle est vérifiée ou non. :githublink:`%|py|35` """
[docs] def correcte(self, cases): """ cette méthode doit être surchargée :githublink:`%|py|40` """ raise NotImplementedError()
[docs]class Regle1(Regle): """ implémente la première règle :githublink:`%|py|47` """
[docs] def correcte(self, cases): """ vérifie qu'on a bien le bon nombre de types de fioles :githublink:`%|py|52` """ nb = [0, 0, 0, 0] for s in cases: nb[s.contenu] += 1 if nb[0] != 3: return False # 3 poison if nb[1] != 2: return False # 2 vin if nb[2] != 1: return False # 1 reculer if nb[3] != 1: return False # 1 avancer return True
[docs]class Regle2(Regle): """ implémente la seconde règle :githublink:`%|py|70` """
[docs] def correcte(self, cases): """ vérifie le voisi n de reculer :githublink:`%|py|75` """ for i in range(1, len(cases)): if cases[i].contenu == 1 and cases[i - 1].contenu != 0: return False return True
[docs]class Regle3(Regle): """ implémente la troisième règle :githublink:`%|py|85` """
[docs] def correcte(self, cases): """ ... :githublink:`%|py|90` """ if cases[0].contenu == cases[6].contenu: return False if cases[0].contenu == 3: return False if cases[6].contenu == 3: return False return True
[docs]class Regle4(Regle): """ implémente la quatrième règle :githublink:`%|py|103` """
[docs] def correcte(self, cases): """ ... :githublink:`%|py|108` """ if cases[2].contenu == 0: return False if cases[5].contenu == 0: return False return True
[docs]class Regle5(Regle): """ implémente la cinquième règle :githublink:`%|py|119` """
[docs] def correcte(self, cases): """ ... :githublink:`%|py|124` """ if cases[1].contenu != cases[5].contenu: return False return True
[docs]class Enigme: """ description de l'énigme :githublink:`%|py|133` """
[docs] def __init__(self): """ constructeur, définit les règles et les cases :githublink:`%|py|138` """ self.regle = [Regle1(), Regle2(), Regle3(), Regle4(), Regle5()] self.cases = [Case("poison") for i in range(0, 7)]
[docs] def __str__(self): """ affiche la solution :githublink:`%|py|145` """ return ", ".join(str(c) for c in self.cases)
[docs] def solution_correcte(self): """ détermine si une solution vérifie toutes les règles :githublink:`%|py|151` """ for r in self.regle: if not r.correcte(self.cases): return False return True
[docs] def resoud(self): """ résoud l'énigme en essayant toutes les combinaisons possibles, ce n'est pas la plus efficace des solutions :githublink:`%|py|161` """ for c in self.cases: c.contenu = 0 while self.cases[0].contenu < 4: r = self.solution_correcte() if r: return self self.cases[6].contenu += 1 # on parcourt les indices en, allant de 6 a 1 inclus for i in range(len(self.cases) - 1, 0, -1): if self.cases[i].contenu >= 4: self.cases[i].contenu = 0 self.cases[i - 1].contenu += 1
[docs]def solution(): """ parcourt toutes les configurations possibles et s'arrête à la première qui satsifait toutes les règles :: from ensae_teaching_cs.special.hermionne_classe import solution print(solution()) :githublink:`%|py|188` """ e = Enigme() e.resoud() return e