Mar-31-2018, 08:46 AM
Hi, thanks for your help. Unfortunately the code doesnt seem to work on windows. When I press "Solve Sudoku" another instance of tkinter shows up. By pressing it again he says that its still calculating but even after waiting for 10 minutes there is no solution printed in python shell.
![[Image: stillrunningwkrcp.jpg]](https://abload.de/img/stillrunningwkrcp.jpg)
@woooee
I am using tkinter but I left out that part of the code because it is a lot and quite messy. Here is the whole code if you are interested:
I have not tried using after() method, yet but I suspect that it would slow down the program substantially because it is called in every backtracking step. For example if there are 10k backtracks needed for a certain sudoku, the program would need 1000s longer than normal and 10k backtracks are not even a lot.
![[Image: stillrunningwkrcp.jpg]](https://abload.de/img/stillrunningwkrcp.jpg)
@woooee
I am using tkinter but I left out that part of the code because it is a lot and quite messy. Here is the whole code if you are interested:
import time import os from random import randint from tkinter import * class SudokuSolver(Frame): backtrack_ctr = 0 sudoku = [[" " for col in range(9)] for row in range(9)] solution = [[" " for col in range(9)] for row in range(9)] def __init__(self, parent): Frame.__init__(self, parent, name='frame') self.parent = parent self.initUI() self.newSUDOKU() def initUI(self): self.message_txt = StringVar() self.values = {} self.parent.title('Sudoku Solver') self.pack(fill=BOTH, expand=True) self.message = Label(self, textvariable=self.message_txt) self.message.grid(row=10,column=0,columnspan=8, sticky=E+W) self.solveBtn = Button(self, text="solve",width=6,command=self.solveSUDOKU) self.solveBtn.grid(row=0,column=0) self.newBtn = Button(self, text="new",width=6,command=self.newSUDOKU) self.newBtn.grid(row=0,column=1) self.initBtn = Button(self, text="init",width=6,command=self.initSUDOKU) self.initBtn.grid(row=0,column=2) self.printBtn = Button(self, text="print",width=6,command=self.printSUDOKU) self.printBtn.grid(row=0,column=8) self.checkBtn = Button(self, text="check",width=6,command=self.checkSOLUTION) self.checkBtn.grid(row=0,column=6) self.saveBtn = Button(self, text="save",width=6,command=self.saveSUDOKU) self.saveBtn.grid(row=0,column=7) # ----- make all fields empty ----- # def newSUDOKU(self): self.message_txt.set('') for row in range(9): for col in range(9): self.sudoku[row][col] = ' ' self.solution[row][col] = ' ' self.numEntry = Entry(self, width=5, justify=CENTER, font="Helvetica 12 bold") self.values[row,col] = self.numEntry self.numEntry.grid(row=row+1,column=col, ipady=5) # ----- get random Sudoku from textfiles ----- # def initSUDOKU(self): self.newSUDOKU() self.message_txt.set('') L = len(os.listdir(os.getcwd() + "\sudokus")) / 2 sudokuFile = open(os.getcwd() + "\sudokus\Sudoku%s.txt" % (randint(1, L))) # ----- fill sudoku_original array with values from textfile ----- # row, col = 0, 0 for value in sudokuFile.read(): if value.isdigit() or value==' ': self.sudoku[row][col]=value col += 1 if col==9: if row==8: break row += 1 col = 0 sudokuFile.close() self.sudoku_original = self.copy(self.sudoku) for row in range(9): for col in range(9): value = self.sudoku[row][col] if value!=' ': self.values[row,col].insert(0,value) # ----- write user input into values{} ----- # def getinput(self, matrix): for row in range(9): for col in range(9): value = self.values[row,col].get() if value=='': matrix[row][col] = ' ' elif len(value)!=1: matrix[row][col] = ' ' elif not value.isdigit(): matrix[row][col] = ' ' elif int(value)<1 or int(value)>9: matrix[row][col] = ' ' else : matrix[row][col] = value # ----- print matrix ----- # def printMATRIX(self, matrix): for row in range(9): print("|-----------------------------------|") for col in range(9): print("| " + matrix[row][col] + " ",end='') print("|") print("|-----------------------------------|") # ----- save sudoku ----- # def saveSUDOKU(self): CHECK = self.checkSUDOKU(self.solution) if CHECK[0] and CHECK[1]: num = 1 while os.path.isfile(os.getcwd() + "\sudokus\sudoku%s.txt" % num): num += 1 sudokuFile = open(os.getcwd() + "\sudokus\sudoku%s.txt" %num, 'w') solutionFile = open(os.getcwd() + "\sudokus\solution%s.txt" %num, 'w') for row in range(9): for col in range(9): sudokuFile.write(self.sudoku_original[row][col]) solutionFile.write(self.solution[row][col]) sudokuFile.write('\n') solutionFile.write('\n') sudokuFile.close() solutionFile.close() print("FILES SAVED!") self.message_txt.set("Files saved...") # ----- print sudoku_original, sudoku, solution ----- # def printSUDOKU(self): print("Original : ") self.printMATRIX(self.sudoku_original) print("Sudoku : ") self.printMATRIX(self.sudoku) print("Solution : ") self.printMATRIX(self.solution) if not self.checkSUDOKU(self.sudoku)[0]: print("sudoku is not valid") # ----- check if this input leads to a valid solution ----- # def consistent(self, matrix, row, col, value): for i in range(9): if matrix[row][i]==value: return False if matrix[i][col]==value: return False rowStart = row - row%3 colStart = col - col%3 for m in range(3): for k in range(3): if matrix[rowStart+k][colStart+m]==value: return False return True # ----- check if user input makes sense -----# def checkSUDOKU(self, matrix): valid, complete, rowM, colM, ctr = True, True, 0, 0, 0 for row in range(9): for col in range(9): value = matrix[row][col] if value!=' ': matrix[row][col]=' ' if not self.consistent(matrix,row,col,value): valid, complete = False, True rowM, colM = row+1, col+1 print("MISTAKE AT row=%s ,col=%s" % (row+1, col+1)) return valid, complete, rowM, colM matrix[row][col] = value ctr += 1 else: complete = False if ctr<17: valid = False return valid, complete, rowM, colM # ----- check if solution is valid ----- # def checkSOLUTION(self): self.getinput(self.sudoku) CHECK = self.checkSUDOKU(self.sudoku) if CHECK[0] and CHECK[1]: self.message_txt.set("Solution correct!") elif not CHECK[1]: self.message_txt.set("Sudoku is not complete!") elif not CHECK[0]: self.message_txt.set("Mistake at row %s, col %s" % (CHECK[2], CHECK[3])) # ----- returns an exact copy of 2dim array ----- # def copy(self, matrix): matrix_copy = [[" " for col in range(9)] for row in range(9)] for row in range(9): for col in range(9): matrix_copy[row][col] = matrix[row][col] return matrix_copy # ----- solve current sudoku ----- # def solveSUDOKU(self): self.getinput(self.sudoku) # get user input from GUI and write it into sudoku arrey if not self.checkSUDOKU(self.sudoku)[0]: # check if user input makes sense self.message_txt.set("This sudoku does not have a solution") # ----- save time how long the solving took ----- # else: start = time.time() solve(0) # start backtracking end = time.time() self.message_txt.set("%s seconds, %s backtracks"%(round((end-start),3) ,self.backtrack_ctr)) self.backtrack_ctr = 0 # reset backtrack counter # ----- fill all fields with the solution ----- # for row in range(9): for col in range(9): self.values[row,col].delete(0,END) self.values[row,col].insert(0,self.solution[row][col]) # ----- backtracking algorithm ----- # def solve(num): SudokuSolver.backtrack_ctr += 1 if num==81: print("Solution found!") SudokuSolver.solution = SudokuSolver.copy(SudokuSolver,SudokuSolver.sudoku) return True else: row = int(num / 9) col = num % 9 if SudokuSolver.sudoku[row][col]!=' ': solve(num+1) else: for value in range(1,10): if SudokuSolver.consistent(SudokuSolver,SudokuSolver.sudoku, row,col,str(value)): SudokuSolver.sudoku[row][col]=str(value) if solve(num+1): return True SudokuSolver.sudoku[row][col]=' ' return False def main(): root = Tk() app = SudokuSolver(root) root.mainloop() if __name__== '__main__': main()if you want the init function to work you have to create a folder called "sudokus" and save it to your working directory. Within that folder you create a .txt file called "sudoku1.txt" with the following content:
21 73 58 43 2 8 76 25 73 98all spaces needed
I have not tried using after() method, yet but I suspect that it would slow down the program substantially because it is called in every backtracking step. For example if there are 10k backtracks needed for a certain sudoku, the program would need 1000s longer than normal and 10k backtracks are not even a lot.