Coverage for src/ensae_teaching_cs/special/hermionne_classes.py: 96%
78 statements
« prev ^ index » next coverage.py v7.1.0, created at 2023-04-28 06:23 +0200
« prev ^ index » next coverage.py v7.1.0, created at 2023-04-28 06:23 +0200
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Implémentation de la résolution de l'énigme d'Hermionne (Harry Potter tome 1)
5avec des classes.
6`logique <https://fr.wikipedia.org/wiki/R%C3%A8gle_de_r%C3%A9solution>`_.
7"""
10class Case:
11 """
12 L'énigme d'Hermionne repose sur 7 cases disposées en ligne.
13 Cette classe définit une case.
14 """
15 contenu_case = ["poison", "vin", "reculer", "avancer"]
17 def __init__(self, contenu):
18 """
19 constructeur
20 """
21 self.contenu = Case.contenu_case.index(contenu)
23 def __str__(self):
24 """
25 affiche le contenu
26 """
27 return Case.contenu_case[self.contenu]
30class Regle:
31 """
32 L'énigme repose sur des règles.
33 Chaque règle hérite de cette classe et implémente la méthode
34 *correcte* qui vérifie si la règle est vérifiée ou non.
35 """
37 def correcte(self, cases):
38 """
39 cette méthode doit être surchargée
40 """
41 raise NotImplementedError()
44class Regle1(Regle):
45 """
46 implémente la première règle
47 """
49 def correcte(self, cases):
50 """
51 vérifie qu'on a bien le bon nombre de types de fioles
52 """
53 nb = [0, 0, 0, 0]
54 for s in cases:
55 nb[s.contenu] += 1
56 if nb[0] != 3:
57 return False # 3 poison
58 if nb[1] != 2:
59 return False # 2 vin
60 if nb[2] != 1:
61 return False # 1 reculer
62 if nb[3] != 1:
63 return False # 1 avancer
64 return True
67class Regle2(Regle):
68 """
69 implémente la seconde règle
70 """
72 def correcte(self, cases):
73 """
74 vérifie le voisi n de reculer
75 """
76 for i in range(1, len(cases)):
77 if cases[i].contenu == 1 and cases[i - 1].contenu != 0:
78 return False
79 return True
82class Regle3(Regle):
83 """
84 implémente la troisième règle
85 """
87 def correcte(self, cases):
88 """
89 ...
90 """
91 if cases[0].contenu == cases[6].contenu:
92 return False
93 if cases[0].contenu == 3:
94 return False
95 if cases[6].contenu == 3:
96 return False
97 return True
100class Regle4(Regle):
101 """
102 implémente la quatrième règle
103 """
105 def correcte(self, cases):
106 """
107 ...
108 """
109 if cases[2].contenu == 0:
110 return False
111 if cases[5].contenu == 0:
112 return False
113 return True
116class Regle5(Regle):
117 """
118 implémente la cinquième règle
119 """
121 def correcte(self, cases):
122 """
123 ...
124 """
125 if cases[1].contenu != cases[5].contenu:
126 return False
127 return True
130class Enigme:
131 """
132 description de l'énigme
133 """
135 def __init__(self):
136 """
137 constructeur, définit les règles et les cases
138 """
139 self.regle = [Regle1(), Regle2(), Regle3(), Regle4(), Regle5()]
140 self.cases = [Case("poison") for i in range(0, 7)]
142 def __str__(self):
143 """
144 affiche la solution
145 """
146 return ", ".join(str(c) for c in self.cases)
148 def solution_correcte(self):
149 """
150 détermine si une solution vérifie toutes les règles
151 """
152 for r in self.regle:
153 if not r.correcte(self.cases):
154 return False
155 return True
157 def resoud(self):
158 """
159 résoud l'énigme en essayant toutes les combinaisons possibles,
160 ce n'est pas la plus efficace des solutions
161 """
162 for c in self.cases:
163 c.contenu = 0
165 while self.cases[0].contenu < 4:
166 r = self.solution_correcte()
167 if r:
168 return self
170 self.cases[6].contenu += 1
171 # on parcourt les indices en, allant de 6 a 1 inclus
172 for i in range(len(self.cases) - 1, 0, -1):
173 if self.cases[i].contenu >= 4:
174 self.cases[i].contenu = 0
175 self.cases[i - 1].contenu += 1
178def solution():
179 """
180 parcourt toutes les configurations possibles
181 et s'arrête à la première qui satsifait toutes les règles
183 ::
185 from ensae_teaching_cs.special.hermionne_classe import solution
186 print(solution())
188 """
189 e = Enigme()
190 e.resoud()
191 return e