From 60191fdd2d7bf947bbdd1df131b78fa3bf006558 Mon Sep 17 00:00:00 2001 From: Johan LACHENAL Date: Mon, 17 Oct 2022 19:45:32 +0000 Subject: [PATCH] =?UTF-8?q?Transf=C3=A9rer=20les=20fichiers=20vers=20'Enig?= =?UTF-8?q?mePython'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de la fonction générique résolvant les cryptarithmes, plusieurs bugs subsistent encore à savoir lorsque l'on fait des cryptarithme de plus de 2 mots et lorsque l'on fait des cryptarithmes avec des soustractions --- EnigmePython/cryptarithme.py | 154 +++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 EnigmePython/cryptarithme.py diff --git a/EnigmePython/cryptarithme.py b/EnigmePython/cryptarithme.py new file mode 100644 index 00000000..78a58c19 --- /dev/null +++ b/EnigmePython/cryptarithme.py @@ -0,0 +1,154 @@ +# file cryptarithme.py +# brief solution générique des cryptarithme +# author Johan Lachenal +# date 17 Octobre 2022 +# ce fichier contient l'algorithme générique résolvant les cryptarithmes, plus tard il contiendra un générateur aléatoire de cryptarithme + +# Pour que le résolveur d'énigmes de cryptarithme fonctionne, il est nécessaire d'effectuer la commande : +# pip install cpmpy + +import numpy as np +import re +import itertools +from cpmpy import * + +# brief résout un cryptarithme donné et affiche le résultat +# param ListeMots liste des mots du cryptarithme entré +# param ListeOperateurs liste des opérateurs du cryptarithme entré +# param ListeLettres liste des lettres associés à des variables du cryptarithme +# param ListePosition liste temporaire servant à prendre les positions des variables dans la liste ListeLettres pour un mot que l'on remet ensuite a null +# param ListePostion liste de liste de positions des variables dans la liste ListeLettres +# param exposant10 liste temporaire servant à prendre les exposants pour chacune des lettres d'un mot +# param exposants10 liste de liste d'exposant pour chque mot +# param ConstraintAssemblingList liste des operations entre les variables d'un mot +# param equalposition postion du egal dans la liste des opérateurs +# param BigFirstEquationConstraintPart partie de contrainte avant le egal +# param BigSecondEquationConstraintPart partie de contrainte après le egal +# param model, model auquel on ajoute les contraintes + +def cryptarithmeGenerique (s): + + ListeMots=[] + ListeOperateurs=[] + ListeLettres=[] + ListePosition=[] + ListePositions=[] + exposant10=[] + exposants10=[] + ConstraintAssemblingList=[] + BigFirstEquationConstraintPart=[] + equalposition=0 + # attrape la liste de lettres + + lettres = "".join(set(re.findall("[A-Z]", s))) + + # attrape la liste de mots + + mots = s.split() + if(mots[0]=='-'): + print("pas de - comme opérateur devant la chaîne de caractère") + return + for i in range(0,len(mots),2): + ListeMots.append(mots[i]) + # print(ListeMots) + + # attrape la liste d'opérateurs + for i in range(1,len(mots),2): + ListeOperateurs.append(mots[i]) + # print(ListeOperateurs) + + # associe à une lettre ses possibilités + + for i in range(0,len(lettres)): + ListeLettres.append([lettres[i],intvar(0,9, shape=1)]) + # print(ListeLettres) + + # associe pour chaque mot une liste des positions des variables contenu dans ListeLettres + + for i in ListeMots: + # print(i) + for y in i: + # print(y) + for w in range(0,len(ListeLettres)): + # print(w) + # print(ListeLettres[w][0]) + if(y==ListeLettres[w][0]): + ListePosition.append(w) + break + ListePositions.append(ListePosition) + ListePosition=[] + # print(ListePositions) + + # associe pour chaque mot une liste d'exposant + + for y in ListeMots: + for i in range(0,len(y)): + exposant10.append(10**i) + exposants10.append(exposant10) + exposant10=[] + # print(exposants10) + + # creation des parties de la contrainte globale du cryptarithme + + for i in range(0,len(ListeMots)): + ConstraintAssemblingList.append(sum([ListeLettres[ListePositions[i][y]][1]*10**(len(ListeMots[i])-y) for y in range(0,len(ListeMots[i]))])) + # print(ConstraintAssemblingList) + + # assemblage des parties de la contrainte globale du cryptarithme avant le = + + for i in range(0,len(ListeOperateurs)): + if(ListeOperateurs[i]=='+'): + BigFirstEquationConstraintPart.append(ConstraintAssemblingList[i]+ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='-'): + BigFirstEquationConstraintPart.append(ConstraintAssemblingList[i]-ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='*'): + BigFirstEquationConstraintPart.append(ConstraintAssemblingList[i]*ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='/'): + BigFirstEquationConstraintPart.append(ConstraintAssemblingList[i]/ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='='): + equalposition=i + break + # print(BigFirstEquationConstraintPart[0]) + + # assemblage des parties de la contrainte globale du cryptarithme après le = + + BigSecondEquationConstraintPart=ConstraintAssemblingList[equalposition+1] + for i in range(equalposition,len(ListeOperateurs)): + if(ListeOperateurs[i]=='+'): + BigSecondEquationConstraintPart.append(ConstraintAssemblingList[i]+ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='-'): + BigSecondEquationConstraintPart.append(ConstraintAssemblingList[i]-ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='*'): + BigSecondEquationConstraintPart.append(ConstraintAssemblingList[i]*ConstraintAssemblingList[i+1]) + if(ListeOperateurs[i]=='/'): + BigSecondEquationConstraintPart.append(ConstraintAssemblingList[i]/ConstraintAssemblingList[i+1]) + # print(BigSecondEquationConstraintPart) + + # Création du model et de ses contraintes + + model = Model() + + # Mise en place de la contrainte globale + + model += (BigFirstEquationConstraintPart[0] == BigSecondEquationConstraintPart) + + # Mise en place de la contrainte où toutes les lettres sont différentes + + model += AllDifferent(ListeLettres[i][1] for i in range(0,len(ListeLettres))) + + # Mise en place de la contrainte disant que les premières lettres des mots sont différentes de 0 + + for i in range(0,len(ListeMots)): + model += (ListeLettres[ListePositions[i][0]][1]) > 0 + + + if model.solve(): + print(s) + for i in range(0,len(ListeMots)): + print(ListeMots[i]," =",[x.value() for x in [ListeLettres[ListePositions[i][y]][1] for y in range(0,len(ListeMots[i]))]]) + else: + print("No solution found") + +cryptarithmeGenerique("SEND + MORE = MONEY"); +cryptarithmeGenerique("HUIT + HUIT = SEIZE"); +# cryptarithmeGenerique("UN + UN + NEUF = ONZE"); \ No newline at end of file