Python : Cryptogramme Cryptarithm Solver

Résolu
Bonjour,

J'essaie de créer un petit programme pour résoudre des Cryptarythmmes, mais je suis bloqué ...

Contrainte :
- Les nombres doivent tous être compris entre 0 et 9, mais on peut les utiliser plusieurs fois... Par exemple A peut être égal à 1, B = 2, ... Mais C peut aussi être égal à 1... etc

J'aimerai :
- Améliorer le processus pour que justement la contrainte chiffre de 0 à 9 soit possible pour plusieurs lettres.
- Intégrer une résolution globale pour que A (par exemple) soit le même chiffre dans l'ensemble des équations.

Est-ce quelqu'un pourrait m'aider s'il vous plaît ?
Je débute dans Python, alors n'hésitez pas à illustrer vos propos avec les lignes de codes.

Par avance merci à tout ceux qui m'aideront.

Voici ce que j'ai déjà fait :

from time import time

def solve(text):
    text = text.replace(" ", "")
    lhs, rhs = [[term[::-1] for term in s.split("+")] for s in text.split("=")]
    signs = [1]*len(lhs) + [-1]*(len(rhs)-1)
    lhs.extend(rhs[:-1])
    dic = {}
    maxlen = max(len(rhs[-1]), max(map(len, lhs)))
    return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None

def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
    if col==maxlen:
        return carry==0
    if row==len(lhs):
        if col>=len(rhs):
            return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if rhs[col] in dic:
            return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if carry%10 not in unused:
            return False
        dic[rhs[col]]=carry%10
        if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
            return True
        del dic[rhs[col]]
        return False
    if col>=len(lhs[row]):
        return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
    if lhs[row][col] in dic:
        return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
            and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                           carry+signs[row]*dic[lhs[row][col]], maxlen)
    for digit in unused:
        if digit!=0 or col<len(lhs[row])-1:
            dic[lhs[row][col]]=digit
            if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                          carry+signs[row]*digit, maxlen):
                return True
    return False

    text = text.replace(" ", "")
    lhs, rhs = [[term[::-1] for term in s.split("*")] for s in text.split("=")]
    signs = [1]*len(lhs) * [-1]*(len(rhs)-1)
    lhs.extend(rhs[:-1])
    dic = {}
    maxlen = max(len(rhs[-1]), max(map(len, lhs)))
    return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None

def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
    if col==maxlen:
        return carry==0
    if row==len(lhs):
        if col>=len(rhs):
            return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if rhs[col] in dic:
            return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if carry%10 not in unused:
            return False
        dic[rhs[col]]=carry%10
        if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
            return True
        del dic[rhs[col]]
        return False
    if col>=len(lhs[row]):
        return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
    if lhs[row][col] in dic:
        return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
            and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                           carry+signs[row]*dic[lhs[row][col]], maxlen)
    for digit in unused:
        if digit!=0 or col<len(lhs[row])-1:
            dic[lhs[row][col]]=digit
            if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                          carry+signs[row]*digit, maxlen):
                return True
            del dic[lhs[row][col]]
    return True
    return False

    text = text.replace(" ", "")
    lhs, rhs = [[term[::-1] for term in s.split("-")] for s in text.split("=")]
    signs = [-1]*len(lhs) - [1]*(len(rhs)-1)
    lhs.extend(rhs[:-1])
    dic = {}
    maxlen = max(len(rhs[-1]), max(map(len, lhs)))
    return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None

def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
    if col==maxlen:
        return carry==0
    if row==len(lhs):
        if col>=len(rhs):
            return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if rhs[col] in dic:
            return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if carry%10 not in unused:
            return False
        dic[rhs[col]]=carry%10
        if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
            return True
        del dic[rhs[col]]
        return False
    if col>=len(lhs[row]):
        return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
    if lhs[row][col] in dic:
        return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
            and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                           carry+signs[row]*dic[lhs[row][col]], maxlen)
    for digit in unused:
        if digit!=0 or col<len(lhs[row])-1:
            dic[lhs[row][col]]=digit
            if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                          carry+signs[row]*digit, maxlen):
                return True
            del dic[lhs[row][col]]
    return True
    return False

    text = text.replace(" ", "")
    lhs, rhs = [[term[::-1] for term in s.split("/")] for s in text.split("=")]
    signs = [-1]*len(lhs) / [1]*(len(rhs)-1)
    lhs.extend(rhs[:-1])
    dic = {}
    maxlen = max(len(rhs[-1]), max(map(len, lhs)))
    return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None

def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
    if col==maxlen:
        return carry==0
    if row==len(lhs):
        if col>=len(rhs):
            return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if rhs[col] in dic:
            return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
        if carry%10 not in unused:
            return False
        dic[rhs[col]]=carry%10
        if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
            return True
        del dic[rhs[col]]
        return False
    if col>=len(lhs[row]):
        return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
    if lhs[row][col] in dic:
        return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
            and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                           carry+signs[row]*dic[lhs[row][col]], maxlen)
    for digit in unused:
        if digit!=0 or col<len(lhs[row])-1:
            dic[lhs[row][col]]=digit
            if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                          carry+signs[row]*digit, maxlen):
                return True
            del dic[lhs[row][col]]
    return True
    return False

testCases=["abcd*ef/ad=ea*dgf/he+ecah",
           "ihbgh*ga/hbl=gf*gjad/di+eeck",
           "eihle*dhc/gi=lc*aijbk/fk+dkigk",
           "bacj*fjg/eid=df*hcli/ai+daeia",
           "lkjek*fb/ddd=c*jikgb/egb+elblc",
           "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
           "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
           "ef+ga-dhc+fjg-fb=gfl",
           "ad+hbl-gi-eid-ddd=dbl",
           "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
           "he+di+fk+ai+egb=gcl",
           "ecah-eeck+dkigk+daeia-elblc=bbfg",
           ]
for test in testCases:
    print(test)
    start=time()
    solution=solve(test)
    print(time()-start, "seconds")
    if solution is None:
        print("No solution exists")
    else:
        result="".join(str(solution.get(c, c)) for c in test)
        for key, value in solution.items():
            print(key, '=', value)
        print(result)
    print(flush=True)

8 réponses

Résumé de la discussion

La discussion porte sur la création d'un petit solveur cryptarithmetic en Python, avec contraintes numériques 0 à 9 réutilisables et cohérence des lettres sur l'ensemble des équations. Plusieurs intervenants examinent des implémentations où résoudre l'addition, la multiplication et d'autres opérations exige une mapping unique des lettres vers des chiffres et un tableau "unused". Le fil aborde des bugs fréquents tels que la duplication de solve_impl, des tests avec des cas simples comme a=b+2, et des améliorations pour éviter des échecs. D'autres échanges insistent sur l'importance de partager le code avec une indentation correcte et proposent des cas de tests variés pour évaluer robustesse et performance.

Bobot (l’IA à votre service)
  1. Pouvez-vous me montrer la correction ?
    1. Contributeur
      je pense que tu progresseras mieux en le faisant toi-même. regarde ce que tu as partagé en #17.
    2. @yg_beje ne vois pas ce que je dois corriger...
      le len ?
      le carry ?
    3. Contributeur
      @Wubittas-tu encore plusieurs lignes
      def solve_impl
      ?
    4. @yg_bej'aurais besoin d'un indice sur ce que je dois corriger, s'il vous plaît... je ne trouve pas l'erreur.
  2. reste à ajouter l'option que les chiffres peuvent être les mêmes pour deux lettres ou plus différentes.
    1. Contributeur
      je pense qu'il suffit de ne jamais rien retirer de unused.
    2. @yg_beCela ne semble pas suffire.... Une seule autre équation est résolue :

      he+di+fk+ai+egb=gcl
      0.00021886825561523438 seconds
      e = 3
      i = 9
      k = 9
      b = 9
      h = 9
      d = 6
      f = 6
      a = 6
      g = 6
      l = 9
      c = 6
      93+69+69+69+369=669

      et une autre ne l'est plus...
    3. @yg_beVoici celle qui a disparu : SEND+MORE=MONEY
    4. Contributeur
      @Wubittchez moi, elle fonctionne. as-tu encore plusieurs lignes
      def solve_impl
      ?
      commence par corriger cela.
  3. voilà, c'est corrigé et cela fonctionne :

    from time import time
    
    def solve(text):
        text = text.replace(" ", "")
        lhs, rhs = [[term[::-1] for term in s.split("+")] for s in text.split("=")]
        signs = [1]*len(lhs) + [-1]*(len(rhs)-1)
        lhs.extend(rhs[:-1])
        dic = {}
        maxlen = max(len(rhs[-1]), max(map(len, lhs)))
        return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
    
    def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
        if col==maxlen:
            return carry==0
        if row==len(lhs):
            if col>=len(rhs):
                return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if rhs[col] in dic:
                return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                    and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if carry%10 not in unused:
                return False
            dic[rhs[col]]=carry%10
            if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                return True
            del dic[rhs[col]]
            return False
        if col>=len(lhs[row]):
            return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
        if lhs[row][col] in dic:
            return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                               carry+signs[row]*dic[lhs[row][col]], maxlen)
        for digit in unused:
            if digit!=0 or col<len(lhs[row])-1:
                dic[lhs[row][col]]=digit
                if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                              carry+signs[row]*digit, maxlen):
                    return True
                del dic[lhs[row][col]]
        return True
        return False
    
        text = text.replace(" ", "")
        lhs, rhs = [[term[::-1] for term in s.split("*")] for s in text.split("=")]
        signs = [1]*len(lhs) * [-1]*(len(rhs)-1)
        lhs.extend(rhs[:-1])
        dic = {}
        maxlen = max(len(rhs[-1]), max(map(len, lhs)))
        return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
    
    def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
        if col==maxlen:
            return carry==0
        if row==len(lhs):
            if col>=len(rhs):
                return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if rhs[col] in dic:
                return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                    and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if carry%10 not in unused:
                return False
            dic[rhs[col]]=carry%10
            if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                return True
            del dic[rhs[col]]
            return False
        if col>=len(lhs[row]):
            return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
        if lhs[row][col] in dic:
            return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                               carry+signs[row]*dic[lhs[row][col]], maxlen)
        for digit in unused:
            if digit!=0 or col<len(lhs[row])-1:
                dic[lhs[row][col]]=digit
                if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                              carry+signs[row]*digit, maxlen):
                    return True
                del dic[lhs[row][col]]
        return True
        return False
    
        text = text.replace(" ", "")
        lhs, rhs = [[term[::-1] for term in s.split("-")] for s in text.split("=")]
        signs = [-1]*len(lhs) - [1]*(len(rhs)-1)
        lhs.extend(rhs[:-1])
        dic = {}
        maxlen = max(len(rhs[-1]), max(map(len, lhs)))
        return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
    
    def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
        if col==maxlen:
            return carry==0
        if row==len(lhs):
            if col>=len(rhs):
                return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if rhs[col] in dic:
                return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                    and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if carry%10 not in unused:
                return False
            dic[rhs[col]]=carry%10
            if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                return True
            del dic[rhs[col]]
            return False
        if col>=len(lhs[row]):
            return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
        if lhs[row][col] in dic:
            return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                               carry+signs[row]*dic[lhs[row][col]], maxlen)
        for digit in unused:
            if digit!=0 or col<len(lhs[row])-1:
                dic[lhs[row][col]]=digit
                if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                              carry+signs[row]*digit, maxlen):
                    return True
                del dic[lhs[row][col]]
        return True
        return False
    
        text = text.replace(" ", "")
        lhs, rhs = [[term[::-1] for term in s.split("/")] for s in text.split("=")]
        signs = [-1]*len(lhs) / [1]*(len(rhs)-1)
        lhs.extend(rhs[:-1])
        dic = {}
        maxlen = max(len(rhs[-1]), max(map(len, lhs)))
        return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
    
    def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
        if col==maxlen:
            return carry==0
        if row==len(lhs):
            if col>=len(rhs):
                return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if rhs[col] in dic:
                return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                    and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
            if carry%10 not in unused:
                return False
            dic[rhs[col]]=carry%10
            if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                return True
            del dic[rhs[col]]
            return False
        if col>=len(lhs[row]):
            return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
        if lhs[row][col] in dic:
            return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                               carry+signs[row]*dic[lhs[row][col]], maxlen)
        for digit in unused:
            if digit!=0 or col<len(lhs[row])-1:
                dic[lhs[row][col]]=digit
                if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                              carry+signs[row]*digit, maxlen):
                    return True
                del dic[lhs[row][col]]
        return False
    
    testCases=["a=b+2",
               "SEND+MORE=MONEY",
               "abcd*ef/ad=ea*dgf/he+ecah",
               "ihbgh*ga/hbl=gf*gjad/di+eeck",
               "eihle*dhc/gi=lc*aijbk/fk+dkigk",
               "bacj*fjg/eid=df*hcli/ai+daeia",
               "lkjek*fb/ddd=c*jikgb/egb+elblc",
               "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
               "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
               "ef+ga-dhc+fjg-fb=gfl",
               "ad+hbl-gi-eid-ddd=dbl",
               "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
               "he+di+fk+ai+egb=gcl",
               "ecah-eeck+dkigk+daeia-elblc=bbfg",
               ]
    for test in testCases:
        print(test)
        start=time()
        solution=solve(test)
        print(time()-start, "seconds")
        if solution is None:
            print("No solution exists")
        else:
            result="".join(str(solution.get(c, c)) for c in test)
            for key, value in solution.items():
                print(key, '=', value)
            print(result)
        print(flush=True)


    réponses données :

    a=b+2
    0.0 seconds
    a = 3
    b = 1
    2 = 2
    3=1+2

    SEND+MORE=MONEY
    0.02094292640686035 seconds
    D = 7
    E = 5
    Y = 2
    N = 6
    R = 8
    O = 0
    S = 9
    M = 1
    9567+1085=10652
    1. malheureusement, c'est possible, même si 99% de ce qui est écrit ici est le code trouvé
      1. le voici en plus court :

        from time import time
        
        def solve(text):
            text = text.replace(" ", "")
            lhs, rhs = [[term[::-1] for term in s.split("+")] for s in text.split("=")]
            lhs, rhs = [[term[::-1] for term in s.split("*")] for s in text.split("=")]
            lhs, rhs = [[term[::-1] for term in s.split("-")] for s in text.split("=")]
            lhs, rhs = [[term[::-1] for term in s.split("/")] for s in text.split("=")]
            signs = [1]*len(lhs) + [-1]*(len(rhs)-1)
            lhs.extend(rhs[:-1])
            dic = {}
            maxlen = max(len(rhs[-1]), max(map(len, lhs)))
            return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
        
        def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
            if col==maxlen:
                return carry==0
            if row==len(lhs):
                if col>=len(rhs):
                    return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                if rhs[col] in dic:
                    return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                        and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                if carry%10 not in unused:
                    return False
                dic[rhs[col]]=carry%10
                if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                    return True
                del dic[rhs[col]]
                return False
            if col>=len(lhs[row]):
                return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
            if lhs[row][col] in dic:
                return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                    and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                   carry+signs[row]*dic[lhs[row][col]], maxlen)
            for digit in unused:
                if digit!=0 or col<len(lhs[row])-1:
                    dic[lhs[row][col]]=digit
                    if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                  carry+signs[row]*digit, maxlen):
                        return True
           
        
           
            return True
            return False
        
        testCases=["abcd*ef/ad=ea*dgf/he+ecah",
                   "ihbgh*ga/hbl=gf*gjad/di+eeck",
                   "eihle*dhc/gi=lc*aijbk/fk+dkigk",
                   "bacj*fjg/eid=df*hcli/ai+daeia",
                   "lkjek*fb/ddd=c*jikgb/egb+elblc",
                   "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
                   "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
                   "ef+ga-dhc+fjg-fb=gfl",
                   "ad+hbl-gi-eid-ddd=dbl",
                   "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
                   "he+di+fk+ai+egb=gcl",
                   "ecah-eeck+dkigk+daeia-elblc=bbfg",
                   ]
        for test in testCases:
            print(test)
            start=time()
            solution=solve(test)
            print(time()-start, "seconds")
            if solution is None:
                print("No solution exists")
            else:
                result="".join(str(solution.get(c, c)) for c in test)
                for key, value in solution.items():
                    print(key, '=', value)
                print(result)
            print(flush=True)
        
        1. Malheureusement cela bug pour la deuxième multiplication :
          et surtout j'ai beaucoup moins de résultats d'égalité qu'auparavant...

          ihbgh*ga/hbl=gf*gjad/di+eeck
          3.552436828613281e-05 seconds
          a = 0
          l = 1
          d = 2
          k = 9
          g = 3
          b = 4
          c = 6
          * = 8
          h = 5
          j = 7
          i5435830/541=3f83702/2i+ee69
        2. Contributeur
          cela va mieux, il ne reste qu'une erreur avec les lignes 46 et 47.

          cependant, il ne donne pas de résultat utile, même pour un cas simple comme:
          "a=b+2"
        3. @yg_bevoilà au plus court possible :

          from time import time
          
          def solve(text):
              text = text.replace(" ", "")
              lhs, rhs = [[term[::-1] for term in s.split("+")] for s in text.split("=")]
              signs = [1]*len(lhs) + [-1]*(len(rhs)-1)
              lhs.extend(rhs[:-1])
              dic = {}
              maxlen = max(len(rhs[-1]), max(map(len, lhs)))
              return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
          
          def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
              if col==maxlen:
                  return carry==0
              if row==len(lhs):
                  if col>=len(rhs):
                      return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if rhs[col] in dic:
                      return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                          and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if carry%10 not in unused:
                      return False
                  dic[rhs[col]]=carry%10
                  if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                      return True
                  del dic[rhs[col]]
                  return False
              if col>=len(lhs[row]):
                  return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
              if lhs[row][col] in dic:
                  return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                      and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                     carry+signs[row]*dic[lhs[row][col]], maxlen)
              for digit in unused:
                  if digit!=0 or col<len(lhs[row])-1:
                      dic[lhs[row][col]]=digit
                      if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                    carry+signs[row]*digit, maxlen):
                          return True
             
              return True
              return False
          
          testCases=["a=b+2",
                     "abcd*ef/ad=ea*dgf/he+ecah",
                     "ihbgh*ga/hbl=gf*gjad/di+eeck",
                     "eihle*dhc/gi=lc*aijbk/fk+dkigk",
                     "bacj*fjg/eid=df*hcli/ai+daeia",
                     "lkjek*fb/ddd=c*jikgb/egb+elblc",
                     "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
                     "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
                     "ef+ga-dhc+fjg-fb=gfl",
                     "ad+hbl-gi-eid-ddd=dbl",
                     "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
                     "he+di+fk+ai+egb=gcl",
                     "ecah-eeck+dkigk+daeia-elblc=bbfg",
                     ]
          for test in testCases:
              print(test)
              start=time()
              solution=solve(test)
              print(time()-start, "seconds")
              if solution is None:
                  print("No solution exists")
              else:
                  result="".join(str(solution.get(c, c)) for c in test)
                  for key, value in solution.items():
                      print(key, '=', value)
                  print(result)
              print(flush=True)
          


          Mais effectivement, il doit y avoir un problème car cela me donne :

          a=b+2
          5.817413330078125e-05 seconds
          a = 1
          b = 9
          1=9+2

          !!!!!!
        4. Contributeur
          @Wubittle programme que tu as trouvé sur internet fonctionne-t'il mieux?
          c'est peut-être quand tu l'as transformé qu'il a arrêté de fonctionner.
      2. Bonjour yg_be,

        Je fais cela dans le cadre d'un loisir pour résoudre l'énigme qui est dedans :
        "abcd*ef/ad=ea*dgf/he+ecah",
        "ihbgh*ga/hbl=gf*gjad/di+eeck",
        "eihle*dhc/gi=lc*aijbk/fk+dkigk",
        "bacj*fjg/eid=df*hcli/ai+daeia",
        "lkjek*fb/ddd=c*jikgb/egb+elblc",
        "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
        "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
        "ef+ga-dhc+fjg-fb=gfl",
        "ad+hbl-gi-eid-ddd=dbl",
        "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
        "he+di+fk+ai+egb=gcl",
        "ecah-eeck+dkigk+daeia-elblc=bbfg"

        Je n'ai pas vraiment écrit ce code, je l'ai trouvé sur internet pour additionner et je l'ai transformé pour les 4 opérations...

        Du coup, je cherche à l'étoffer pour résoudre mon énigme dont voici la photo.

        Pour les lignes 159 et 160, cela me permet de voir ou je suis bloqué, mais cela n'aura plus d'utilité à la fin si ce programme fonctionne.

        Merci d'avance pour votre aide.
        1. @yg_be
          from time import time
          
          def solve(text):
              text = text.replace(" ", "")
              lhs, rhs = [[term[::-1] for term in s.split("+")] for s in text.split("=")]
              signs = [1]*len(lhs) + [-1]*(len(rhs)-1)
              lhs.extend(rhs[:-1])
              dic = {}
              maxlen = max(len(rhs[-1]), max(map(len, lhs)))
              return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
          
          def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
              if col==maxlen:
                  return carry==0
              if row==len(lhs):
                  if col>=len(rhs):
                      return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if rhs[col] in dic:
                      return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                          and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if carry%10 not in unused:
                      return False
                  dic[rhs[col]]=carry%10
                  if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                      return True
                  del dic[rhs[col]]
                  return False
              if col>=len(lhs[row]):
                  return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
              if lhs[row][col] in dic:
                  return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                      and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                     carry+signs[row]*dic[lhs[row][col]], maxlen)
              for digit in unused:
                  if digit!=0 or col<len(lhs[row])-1:
                      dic[lhs[row][col]]=digit
                      if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                    carry+signs[row]*digit, maxlen):
                          return True
                      del dic[lhs[row][col]]
              return True
              return False
          
              text = text.replace(" ", "")
              lhs, rhs = [[term[::-1] for term in s.split("*")] for s in text.split("=")]
              signs = [1]*len(lhs) * [-1]*(len(rhs)-1)
              lhs.extend(rhs[:-1])
              dic = {}
              maxlen = max(len(rhs[-1]), max(map(len, lhs)))
              return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
          
          def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
              if col==maxlen:
                  return carry==0
              if row==len(lhs):
                  if col>=len(rhs):
                      return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if rhs[col] in dic:
                      return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                          and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if carry%10 not in unused:
                      return False
                  dic[rhs[col]]=carry%10
                  if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                      return True
                  del dic[rhs[col]]
                  return False
              if col>=len(lhs[row]):
                  return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
              if lhs[row][col] in dic:
                  return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                      and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                     carry+signs[row]*dic[lhs[row][col]], maxlen)
              for digit in unused:
                  if digit!=0 or col<len(lhs[row])-1:
                      dic[lhs[row][col]]=digit
                      if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                    carry+signs[row]*digit, maxlen):
                          return True
                      del dic[lhs[row][col]]
              return True
              return False
          
              text = text.replace(" ", "")
              lhs, rhs = [[term[::-1] for term in s.split("-")] for s in text.split("=")]
              signs = [-1]*len(lhs) - [1]*(len(rhs)-1)
              lhs.extend(rhs[:-1])
              dic = {}
              maxlen = max(len(rhs[-1]), max(map(len, lhs)))
              return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
          
          def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
              if col==maxlen:
                  return carry==0
              if row==len(lhs):
                  if col>=len(rhs):
                      return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if rhs[col] in dic:
                      return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                          and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if carry%10 not in unused:
                      return False
                  dic[rhs[col]]=carry%10
                  if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                      return True
                  del dic[rhs[col]]
                  return False
              if col>=len(lhs[row]):
                  return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
              if lhs[row][col] in dic:
                  return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                      and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                     carry+signs[row]*dic[lhs[row][col]], maxlen)
              for digit in unused:
                  if digit!=0 or col<len(lhs[row])-1:
                      dic[lhs[row][col]]=digit
                      if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                    carry+signs[row]*digit, maxlen):
                          return True
                      del dic[lhs[row][col]]
              return True
              return False
          
              text = text.replace(" ", "")
              lhs, rhs = [[term[::-1] for term in s.split("/")] for s in text.split("=")]
              signs = [-1]*len(lhs) / [1]*(len(rhs)-1)
              lhs.extend(rhs[:-1])
              dic = {}
              maxlen = max(len(rhs[-1]), max(map(len, lhs)))
              return dic if solve_impl(lhs, signs, rhs[-1], dic, set(range(10)), 0, 0, 0, maxlen) else None
          
          def solve_impl(lhs, signs, rhs, dic, unused, row, col, carry, maxlen):
              if col==maxlen:
                  return carry==0
              if row==len(lhs):
                  if col>=len(rhs):
                      return carry%10==0 and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if rhs[col] in dic:
                      return dic[rhs[col]]==carry%10 and (col<len(rhs)-1 or dic[rhs[col]]!=0)\
                          and solve_impl(lhs, signs, rhs, dic, unused, 0, col+1, carry//10, maxlen)
                  if carry%10 not in unused:
                      return False
                  dic[rhs[col]]=carry%10
                  if solve_impl(lhs, signs, rhs, dic, unused-{carry%10}, 0, col+1, carry//10, maxlen):
                      return True
                  del dic[rhs[col]]
                  return False
              if col>=len(lhs[row]):
                  return solve_impl(lhs, signs, rhs, dic, unused, row+1, col, carry, maxlen)
              if lhs[row][col] in dic:
                  return (col<len(lhs[row])-1 or dic[lhs[row][col]]!=0) \
                      and solve_impl(lhs, signs, rhs, dic, unused, row+1, col,
                                     carry+signs[row]*dic[lhs[row][col]], maxlen)
              for digit in unused:
                  if digit!=0 or col<len(lhs[row])-1:
                      dic[lhs[row][col]]=digit
                      if solve_impl(lhs, signs, rhs, dic, unused-{digit}, row+1, col,
                                    carry+signs[row]*digit, maxlen):
                          return True
                      del dic[lhs[row][col]]
              return True
              return False
          
          testCases=["abcd*ef/ad=ea*dgf/he+ecah",
                     "ihbgh*ga/hbl=gf*gjad/di+eeck",
                     "eihle*dhc/gi=lc*aijbk/fk+dkigk",
                     "bacj*fjg/eid=df*hcli/ai+daeia",
                     "lkjek*fb/ddd=c*jikgb/egb+elblc",
                     "ekjhl-gfl-dbl=gaaeli-gdhbhb-gcl-bbfg",
                     "abcd+ihbgh-eihle-bacj-lkjek=ekjhl",
                     "ef+ga-dhc+fjg-fb=gfl",
                     "ad+hbl-gi-eid-ddd=dbl",
                     "dgf*gjad-aijbk-hcli-jikgb=gdhbhb",
                     "he+di+fk+ai+egb=gcl",
                     "ecah-eeck+dkigk+daeia-elblc=bbfg",
                     ]
          for test in testCases:
              print(test)
              start=time()
              solution=solve(test)
              print(time()-start, "seconds")
              if solution is None:
                  print("No solution exists")
              else:
                  result="".join(str(solution.get(c, c)) for c in test)
                  for key, value in solution.items():
                      print(key, '=', value)
                  print(result)
              print(flush=True)
        2. @yg_beJe l'ai remis... Est-ce mieux ainsi ?
        3. Contributeur
          @Wubittregarde les lignes 161 et 162: qu'en penses-tu?
        4. @yg_beElles ne servent à rien apparemment