Coverage for src/ensae_teaching_cs/special/hermionne_classes.py: 96%

78 statements  

« prev     ^ index     » next       coverage.py v7.1.0, created at 2023-01-27 05:44 +0100

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""" 

8 

9 

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"] 

16 

17 def __init__(self, contenu): 

18 """ 

19 constructeur 

20 """ 

21 self.contenu = Case.contenu_case.index(contenu) 

22 

23 def __str__(self): 

24 """ 

25 affiche le contenu 

26 """ 

27 return Case.contenu_case[self.contenu] 

28 

29 

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 """ 

36 

37 def correcte(self, cases): 

38 """ 

39 cette méthode doit être surchargée 

40 """ 

41 raise NotImplementedError() 

42 

43 

44class Regle1(Regle): 

45 """ 

46 implémente la première règle 

47 """ 

48 

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 

65 

66 

67class Regle2(Regle): 

68 """ 

69 implémente la seconde règle 

70 """ 

71 

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 

80 

81 

82class Regle3(Regle): 

83 """ 

84 implémente la troisième règle 

85 """ 

86 

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 

98 

99 

100class Regle4(Regle): 

101 """ 

102 implémente la quatrième règle 

103 """ 

104 

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 

114 

115 

116class Regle5(Regle): 

117 """ 

118 implémente la cinquième règle 

119 """ 

120 

121 def correcte(self, cases): 

122 """ 

123 ... 

124 """ 

125 if cases[1].contenu != cases[5].contenu: 

126 return False 

127 return True 

128 

129 

130class Enigme: 

131 """ 

132 description de l'énigme 

133 """ 

134 

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)] 

141 

142 def __str__(self): 

143 """ 

144 affiche la solution 

145 """ 

146 return ", ".join(str(c) for c in self.cases) 

147 

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 

156 

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 

164 

165 while self.cases[0].contenu < 4: 

166 r = self.solution_correcte() 

167 if r: 

168 return self 

169 

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 

176 

177 

178def solution(): 

179 """ 

180 parcourt toutes les configurations possibles 

181 et s'arrête à la première qui satsifait toutes les règles 

182 

183 :: 

184 

185 from ensae_teaching_cs.special.hermionne_classe import solution 

186 print(solution()) 

187 

188 """ 

189 e = Enigme() 

190 e.resoud() 

191 return e