Reputation:
I tried to create a sudoku solver algorithm using python and based on backtracking but it always return nothing saying that the sudoku is incorrect.
Here is my code:
board = [[3,0,6,5,0,8,4,0,0],
[5,2,0,0,0,0,0,0,0],
[0,8,7,0,0,0,0,3,1],
[0,0,3,0,1,0,0,8,0],
[9,0,0,8,6,3,0,0,5],
[0,5,0,0,9,0,6,0,0],
[1,3,0,0,0,0,2,5,0],
[0,0,0,0,0,0,0,7,4],
[0,0,5,2,0,6,3,0,0]]
e = [0, 0]
def checkEmpty():
for i in range(0, 9):
for j in range(0, 9):
if board[i][j] == 0:
e[0] = i
e[1] = j
return True
return False
def vLine(i, test):
for j in range(9):
if board[i][j] == test:
return True
return False
def vColumn(j, test):
for i in range(9):
if board[i][j] == test:
return True
return False
def vBlock(i, j, test):
for I in range(3):
for J in range(3):
if(board[i+I][j + J] == test):
return True
return False
def validMove(i, j, test):
if vColumn(j, test) == False and vBlock(i, j, test) == False and vLine(i, test) == False:
return True
else:
return False
def solve():
e = [0, 0]
if checkEmpty() == False:
return True
i = e[0]
j = e[1]
for k in range(1, 10):
if validMove(i, j, k) == True:
board[i][j] = k
if solve() == True:
return True
board[i][j] = 0
return False
if solve():
print("solved!")
else:
print("No solution exists")
The problem is that the code inside this if function if validMove(i, j, k) == True:
seems to never be executed.
However I was unable to find any error in this function.
In addition, I don't really know whether I should indent, dedent or keep this line board[i][j] = 0
here.
Upvotes: 0
Views: 121
Reputation: 51643
Your block checker is wrong - if you input 2,2,9 it will not check the correct block but something misaligned.
def vBlock(i, j, test):
for I in range(3):
for J in range(3):
if(board[i+I][j + J] == test): # checks 2-5. 2-5 row&col
return True
return False
Change it to
def vBlock(i, j, test):
for I in range(3):
for J in range(3):
if(board[i//3+I][j//3 + J] == test): # this way it cecks the blocks correctly
# if you input 2,2,9 it checks 2//3+range == 0+0-3
return True
return False
This wont change the overall error, but compensate for one error at least.
You recurse into solve()
without ever changing the e
-list of row/col currently checked - your solve()
works on a local variable e
- your checkEmpty()
changes the global e
, the changes are never reflected inside solve()
.
Fix:
def checkEmpty():
global e # explicitly use the global e
for i in range(0, 9):
for j in range(0, 9):
if board[i][j] == 0:
e[0] = i
e[1] = j
return True
return False
def solve():
global e # explicitly use the global e
if checkEmpty() == False:
return True
i = e[0]
j = e[1]
print(e)
for k in range(1, 10):
if validMove(i, j, k) == True:
board[i][j] = k
if solve() == True:
return True
board[i][j] = 0
return False
Even if you fix those 2 errors:
You need to be able to discard ealier finds- f.e. at start one space might be able to be filled by 9,1,3,4 - you check 1 first - bingo - put it in, but run into problems later for the spot in this block that was only ever able to hold 1. Now 1 is given away and you have no solution.
You need to calculate "all possible" numbers for all of your 0
first, then fill in those with only 1 possibility, removing that number from the corresponding row/column/block 0
possibilitie lists and continue until all are filled in.
Bottom line: solving it using the first choice available might end you in a local minimun that solves 10 of 12 leftover zeros, and then you are stuck.
Upvotes: 1