Soucis Programme Sudoku

Résolu/Fermé
whathecha Messages postés 5 Date d'inscription lundi 1 octobre 2018 Statut Membre Dernière intervention 1 octobre 2018 - 1 oct. 2018 à 17:11
whathecha Messages postés 5 Date d'inscription lundi 1 octobre 2018 Statut Membre Dernière intervention 1 octobre 2018 - 1 oct. 2018 à 19:01
Bonjour,

Quand on débute en Python qui dit backtracking dit souvent sudoku

alors, j'ai un petit problème dans ma fonction résoudre,

en effet, celle-ci ne sauvegarde pas la solution dans mon objet p.grille :


Je n'arrive pas vraiment à trouver pourquoi. De plus, comme vous pouvez le constater sur la capture, les grilles à résoudre nous sont donné en une ligne (les 9 premiers nombres correspondent à la première ligne, les 9 d'après à la deuxième etc...) sauf que quand cette ligne commence par un zéro et finit par un zéro, ma fonction saisir_sudoku considère que je n'ai pas saisi 81 caractères. là encore, je ne trouve pas mon erreur.

Bref, j'ai besoin d'aide pour régler ces deux derniers petits détails, merci d'avance !

Mon code :

class Sudoku:
        x=[]
        def __init__(self):
                lignes=9
                colonnes=9
                grid=[[0]*colonnes for i in range (lignes)]
                self.grille=grid
                self.column=len(self.grille)
                self.line=len(self.grille[0])

        def lire_fichier_sudoku(self,fichier,ligne):
                with open(fichier,"r") as fich:
                        for i in range(ligne):
                                l=fich.readline().rstrip("\n\r")
                                x=list(map(int,list(str(l))))
                        i,j=0,0
                        c=0
                        for i in range(9):
                                for j in range(9):
                                        self.grille[i][j]=x[c]
                                        c+=1
                        return self.grille                     
       

        def saisir_sudoku(self):
                s=input("Saisir 81 caractères entre 0 et 9")
                try:
                        s=int(s)
                        x=list(map(int,list(str(s))))                                       
                        assert len(x)==81
                                
                        i,j=0,0
                        c=0
                        for i in range(9):
                                for j in range(9):
                                        self.grille[i][j]=x[c]
                                        c+=1
                        return self.grille                     
                               
                
                
                except AssertionError:
                
                        print("Vous n'avez pas saisi 81 caractères !")

                except ValueError:
                        print(" Attention, vous ne pouvez entrer que des caractères numériques !")

        




        def afficher_sudoku(self):
                i,j=0,0
                
                for i in range(9):
                        if i%3==0:
                                print ("--------------")                                
                        for j in range(9):
                                if j%3==0:
                                        print("|",end="")
                                print (self.grille[i][j],end="")
                        print ("|")
                print ("--------------")

        

        


        def position(self,x):
                #donne la ou lespositions du nombre x dans la grille#
                liste=[]
                for i in range(9):
                        for j in range(9):
                                if self.grille[i][j]==x:
                                        liste.append((i,j))

                return liste

        def resoudre_simple(self):
                #resoud un sudoku "simple"#
                M= [[ [0 for col in range(10)] for col in range(9)] for row in range(9)] 
                
                
                for i in range(9):
                        for j in range(9):
                                for k in range(1,10):
                                        
                                       
                                        
                                        

                                        if self.grille[i][j]==k:
                                                for m in range(9):
                                                
                                                                                                                               
                                                        M[m][j][k]=1
                                                        M[i][m][k]=1
                                                for r in range(len(self.position(k))):
                                                  
                                                               x,y=self.position(k)[r]
                                                               for l in range(0,9,3):
                                                                       for c in range(0,9,3):
                                                                               if l<=x<(l+3) and c<=y<(c+3):
                                                                                       M[l][c][k]=1
                                                                
                                                
                                         
                for i in range(9):
                        for j in range(9):
                                for k in range(1,10):                           
                
                
                                        if M[i][j][k]==0:
                                                self.grille[i][j]=k

                if self.est_Valide()==1:
                        return self.afficher_sudoku()
                else:
                        return "Le sudoku n'est probablement pas simple"

        def recherche_zero(self):
                #recherche case vide#
                i0=10
                j0=10
                sortie=0
                for i in range(9):
                        for j in range(9):
                                if self.grille[i][j]==0:
                                        i0=i
                                        j0=j
                                        sortie=1
                                        break
                        if sortie:
                                break
                return (i0,j0)

        def int_valide(self,i,j,num):
                #vérifie si num+1 est valide dans la case de coordonnées i,j#
                for k in range(9):
                    if k!=i:
                        if self.grille[k][j]==num:
                            return False
                    if k!=j:
                        if self.grille[i][k]==num:
                            return False
                            
                ip=int(i/3)*3;
                jp=int(j/3)*3;
                for k in range(3):
                        for l in range(3):
                            if (ip+k)!=i and (jp+l)!=j:

                                if self.grille[ip+k][jp+l]==num:
                                        return False
                return True

        def est_Valide(self):
                for i in range(9):
                        for j in range(9):
                                b=self.grille[i][j]
                                
                                
                                if  not self.int_valide(i,j,b):
                                              
                                                return -1
                return 1
                                                

        def resoudre(self):
                #resoud un sudoku quelconque#
                (i,j)=self.recherche_zero()

                if i==10:
                        self.afficher_sudoku()
                       
                else:
                        for k in range(1,10):
                                if self.int_valide(i,j,k):
                                        self.grille[i][j]=k
                                        
                                        self.resoudre()
                                self.grille[i][j]=0




1 réponse

Utilisateur anonyme
Modifié le 1 oct. 2018 à 17:43
Bonjour

Pour ton problème de zéro en début de saisie :
        def saisir_sudoku(self):
                s=input("Saisir 81 caractères entre 0 et 9")
                try:
                        s=int(s)
                        x=list(map(int,list(str(s)))) 

Je ne connais pas python, mais je suppose qu'avec int(s) tu transformes ta saisie en nombre. Donc tu transformes '3', '03' et '003' en 3 tout court. C'est d'autant plus bête que la ligne suivante, tu fais un str(s) qui re-transforme ce nombre en chaîne, alors que tu avais une chaîne au départ !

Quant à ta solution qui n'est pas sauvegardée, c'est que tu n'as rien fait pour. Quand tu la trouves, tu l'affiches mais tu n'as rien qui empêche de parcourir toutes les possibilités. Tu quittes la fonction resoudre pour retomber dans la boucle 'for k' de niveau supérieur, et cette boucle n'a pas de raison de s'arrêter. Il faudrait mettre une variable booléenne quand tu as trouvé une solution, et arrêter toutes tes boucle for k quand cette variable est positionnée.
1
whathecha Messages postés 5 Date d'inscription lundi 1 octobre 2018 Statut Membre Dernière intervention 1 octobre 2018
1 oct. 2018 à 18:06
Je comprends ce que tu veux dire
Concernant le problème de zéro, c'est réglé en enlevant s=int(s)

En revanche, concernant l'autre problème, toujours rien
Ce qui est bizarre, c'est que si je demande un print de ma grille dans le if i==10, ça fonctionne. Mais si je fais un self.grille dans le shell, ça m'affiche toujours la grille initiale
0
Utilisateur anonyme
1 oct. 2018 à 18:22
Tu n'as pas compris mon explication.
Quand tu as trouvé la solution, tu n'arrêtes pas la recherche : les boucles 'for k' continuent. Or, à la fin de chaque boucle, tu remets les '0' dans ton objet :
self.grille[i][j]=0
. Normal qu'à la fin tu retrouves tous tes '0' initiaux.
0
whathecha Messages postés 5 Date d'inscription lundi 1 octobre 2018 Statut Membre Dernière intervention 1 octobre 2018
1 oct. 2018 à 18:25
Effectivement merci, ça a marché comme ça :

else:
                                       
            
                        
                                for k in range(1,10):
                                                                                                                              
                                        
                                        if self.int_valide(i,j,k):
                                                self.grille[i][j]=k                                    
                                        
                                                self.resoudre()
                                if self.est_Valide()==-1:
                                                
                                
                                        self.grille[i][j]=0
0
Utilisateur anonyme
1 oct. 2018 à 18:41
Tant mieux que ça marche, mais ta manière d'éviter la remise à zéro est extrêmement coûteuse : tu continues de faire tourner les boucles alors que ça ne sert plus à rien, et tu refais appel à est_Valide, qui est compliquée, alors que tu sais qu'une fois que la grille est bonne, elle le reste.
0
whathecha Messages postés 5 Date d'inscription lundi 1 octobre 2018 Statut Membre Dernière intervention 1 octobre 2018
1 oct. 2018 à 18:49
Je vais essayer de trouver une solution moins lourde.
Dernière petite question, sais tu comment éviter l'affichage de la solution ? Même en supprimant mon self.afficher_sudoku(), elle continue à s'afficher
0