[英]Error in writing a backtracking solver for sudoku
所以最近我試圖寫一個回溯方法來解決一個數獨難題(二維列表),我遇到了一些我似乎無法弄清楚調試的錯誤。
我的代碼:
def areLegalValues(values: list):
if len(values) in [1,4,9,16,25]:
for value in values:
if value <= len(values):
if value != 0 and values.count(value)>1:
return False
else:
return False
return True
return False
def isLegalRow(board: list, row: list):
compareList = [ ]
for r in range(len(board)):
if r == row:
for c in range(len(board[0])):
#print(board[r][c])
compareList.append(board[r][c])
return areLegalValues(compareList)
def isLegalCol(board: list, col: list):
compareList = [ ]
for r in range(len(board)):
for c in range(len(board[0])):
if c == col:
compareList.append(board[r][c])
#print(compareList)
return areLegalValues(compareList)
def isLegalBlock(board: list, block: list):
compareList = [ ]
N = int((len(board))**(1/2))
blockRowNumber = int(block//N)
blockColNumber = int(block%N)
for row in range(blockRowNumber*N, blockRowNumber*N+N):
#print(row)
for col in range(len(board[0])):
if col in range(blockColNumber*N, blockColNumber*N+N):
#print(board[row][col])
compareList.append(board[row][col])
# print(compareList)
return areLegalValues(compareList)
def isLegalSudoku(board: list):
boardLength = len(board)
for row in range(len(board)):
if isLegalRow(board,row) != True:
return False
for col in range(len(board[0])):
if isLegalCol(board,col) != True:
return False
for block in range(boardLength):
if isLegalBlock(board, block) != True:
return False
return True
def solveSudoku(board, row=0):
if row == len(board):
return board
else:
for col in range(len(board[row])):
if board[row][col] == 0:
for number in range(1, len(board)+1):
board[row][col] == number
if isLegalSudoku(board) == True:
solution = solveSudoku(board, row+1)
if solution != None:
return solution
board[row][col] == 0
return None
測試代碼:
def testSolveSudoku():
print('Testing solveSudoku()...', end='')
Board = [
[1, 0, 3, 0],
[4, 3, 0, 1],
[2, 0, 1, 0],
[0, 0, 4, 2]
]
Sol = [
[1, 2, 3, 4],
[4, 3, 2, 1],
[2, 4, 1, 3],
[3, 1, 4, 2]
]
print(solveSudoku(Board))
assert(solveSudoku(Board) == Sol)
print('Passed!')
*正如名字所暗示的,isLegalValues 接受一個列表,如果該列表包含合法值,則返回,也就是說,該列表不能有非零數字的重復,0 可以工作。 isLegalRow 和 isLegalCol 遍歷數獨板並建立一個包含特定行/列值的列表並將它們插入 isLegalValues。 isLegalBlock 找到板子中的塊,並獲取一個塊號並將其插入 isLegalValues。 (通過廣泛的測試,這些似乎都有效)
我目前遇到的問題是,由於某種原因,我的代碼完成了解決難題,但設法完成了運行。 例子:
[1, 2, 3, 0],
[4, 3, 2, 1],
[2, 4, 1, 0],
[3, 0, 4, 2]
應該改為
[1, 2, 3, 4],
[4, 3, 2, 1],
[2, 4, 1, 3],
[3, 1, 4, 2]
但我一直返回上面 2 行的代碼。 (帶 0 的那個)
似乎部分代碼正在工作,因為所有被替換的值都是有效的,但回溯似乎有問題。 我想知道是否有人能指出出了什么問題,我該如何解決它?
謝謝
基本上,我犯了一個錯誤,我不斷地用這段代碼跳過同一列中的值,並且也從未嘗試解決最后一列。
解決方案:
def solveSudoku(board: list):
"""takes in a sudoku board and solves the board through use of backtracking
and returns the dectructively changed board"""
checkZeroes = True
for row in range(len(board)):
for col in range(len(board[0])):
if board[row][col] == 0:
checkZeroes = False
if checkZeroes == True:
return board
else:
for row in range(len(board)):
for col in range(len(board[0])):
if board[row][col] == 0:
for number in range(1,len(board)+1):
board[row][col] = number
if isLegalSudoku(board) == True:
solution = solveSudoku(board)
if solution != None:
return solution
board[row][col] = 0
return None
這完成了任務,雖然有點慢,首先檢查整個電路板是否有 0(基本情況),然后循環遍歷電路板中的所有值,如果值為 0,則測試所有可能的值(合法)數字。 然后它檢查整個董事會是否合法,然后繼續。 如果有錯誤,它會回溯。 如果沒有解決方案,則返回 None。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.