一旦解决了难题,如何停止产生数独板?
How to stop yielding sudoku boards, once the puzzle is solved?
这是我的递归数独求解器。非常不言自明:
def is_valid(board, num, row, col):
# check row
for i in range(9):
if board[i][col] == num:
return False
# check column
for i in range(9):
if board[row][i] == num:
return False
# check square
square_w = (row // 3) * 3
square_h = (col // 3) * 3
for sRow in range(square_w, square_w + 3):
for sCol in range(square_h, square_h + 3):
if board[sRow][sCol] == num:
return False
return True
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve(board)
board[row][col] = 0
yield board
return
yield board
这是我的板子运行求解器:
bo = [
[7,8,0,4,0,0,1,2,0],
[6,0,0,0,7,5,0,0,9],
[0,0,0,6,0,1,0,7,8],
[0,0,7,0,4,0,2,6,0],
[0,0,1,0,5,0,9,3,0],
[9,0,4,0,6,0,0,0,5],
[0,7,0,3,0,0,0,1,2],
[1,2,0,0,0,7,4,0,0],
[0,4,9,2,0,6,0,0,7]
]
问题是,当我调用 solve
并迭代生成的板时,即使在获得结果后板仍继续生成(在 solve 函数的最底部 yield board
)。
如何确保生成器中的最后一个值是求解板?
您的代码中存在一些缩进问题。在撰写本文时,return
和 yield from
语句都应多缩进一层。
要在解决后停止生成更多的板,您应该检查板是否已解决。该代码不会在任何地方执行此操作。
正如您正确指出的那样,当您到达 solve
函数中的最后一个语句并且函数 return 在那里时,棋盘已解决。您可以利用这一刻来标记看板,以便呼叫者更容易知道看板已解决。由于您已经在整个算法中改变了同一个板(而不是产生副本),我想您可以再次改变板以表明它已解决。例如,您可以在左上角存储一个 0。这可以由调用者检查,然后调用者可以立即 return:
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve( board) # corrected wrong indentation
if board[0][0] == 0: # was the board already solved?
return # then get out of here!
board[row][col] = 0 # better placed at this indentation
yield board # better placed at this indentation
return # corrected wrong indentation
# the board is the solution: no need to yield it as it was already yielded
board[0][0] = 0 # mark that no more boards should be yielded
这是我的递归数独求解器。非常不言自明:
def is_valid(board, num, row, col):
# check row
for i in range(9):
if board[i][col] == num:
return False
# check column
for i in range(9):
if board[row][i] == num:
return False
# check square
square_w = (row // 3) * 3
square_h = (col // 3) * 3
for sRow in range(square_w, square_w + 3):
for sCol in range(square_h, square_h + 3):
if board[sRow][sCol] == num:
return False
return True
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve(board)
board[row][col] = 0
yield board
return
yield board
这是我的板子运行求解器:
bo = [
[7,8,0,4,0,0,1,2,0],
[6,0,0,0,7,5,0,0,9],
[0,0,0,6,0,1,0,7,8],
[0,0,7,0,4,0,2,6,0],
[0,0,1,0,5,0,9,3,0],
[9,0,4,0,6,0,0,0,5],
[0,7,0,3,0,0,0,1,2],
[1,2,0,0,0,7,4,0,0],
[0,4,9,2,0,6,0,0,7]
]
问题是,当我调用 solve
并迭代生成的板时,即使在获得结果后板仍继续生成(在 solve 函数的最底部 yield board
)。
如何确保生成器中的最后一个值是求解板?
您的代码中存在一些缩进问题。在撰写本文时,return
和 yield from
语句都应多缩进一层。
要在解决后停止生成更多的板,您应该检查板是否已解决。该代码不会在任何地方执行此操作。
正如您正确指出的那样,当您到达 solve
函数中的最后一个语句并且函数 return 在那里时,棋盘已解决。您可以利用这一刻来标记看板,以便呼叫者更容易知道看板已解决。由于您已经在整个算法中改变了同一个板(而不是产生副本),我想您可以再次改变板以表明它已解决。例如,您可以在左上角存储一个 0。这可以由调用者检查,然后调用者可以立即 return:
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_valid(board, num, row, col):
board[row][col] = num
yield board
yield from solve( board) # corrected wrong indentation
if board[0][0] == 0: # was the board already solved?
return # then get out of here!
board[row][col] = 0 # better placed at this indentation
yield board # better placed at this indentation
return # corrected wrong indentation
# the board is the solution: no need to yield it as it was already yielded
board[0][0] = 0 # mark that no more boards should be yielded