python中数独的递归求解
这是代码,python中数独的递归求解,python,recursion,sudoku,Python,Recursion,Sudoku,这是代码,check\u sudoku(grid)可以返回网格是否为有效的数独 我只是不理解递归部分,我试着在纸上写下这个过程,但每次都失败了,回溯是如何工作的?什么是新的?如果答案\u求解\u数独(网格)有效 我知道它每隔0到1..9设置一次,并检查它是否是有效的网格,但我无法在纸上画出整个过程。我真的无法理解回溯是如何工作的 顺便问一下,对于理解递归代码有什么建议吗 致以最良好的祝愿 盛云 编辑 我一次又一次地阅读代码,现在我有了一些理解,但我不太确定这一点,如果有人给我一些意见,我会很感激
check\u sudoku(grid)
可以返回网格是否为有效的数独
我只是不理解递归部分,我试着在纸上写下这个过程,但每次都失败了,回溯是如何工作的?什么是新的?如果答案\u求解\u数独(网格)
有效
我知道它每隔0到1..9设置一次,并检查它是否是有效的网格,但我无法在纸上画出整个过程。我真的无法理解回溯是如何工作的
顺便问一下,对于理解递归代码有什么建议吗
致以最良好的祝愿
盛云
编辑
我一次又一次地阅读代码,现在我有了一些理解,但我不太确定这一点,如果有人给我一些意见,我会很感激的
1、return new
仅在解算器找到解决方案时调用,并在return grid
2、你什么时候来
def answer_solve_sudoku(__grid):
res = check_sudoku(__grid)
if res is None or res is False:
return res
grid = copy.deepcopy(__grid)
# find the first 0 element and change it to each of 1..9,
# recursively calling this function on the result
for row in xrange(9):
for col in xrange(9):
if grid[row][col] == 0:
for n in xrange(1, 10):
grid[row][col] = n
new = answer_solve_sudoku(grid)
if new is not False:
return new
# backtrack
return False
# if we get here, we found no zeros and so we're finished
return grid
被叫来?如果下一个解决方案不正确,check\u sudoku(\u\u grid)
将返回False
,如果下一个解决方案正确,它将调用另一个answer\u solve\u sudoku(grid)
,直到它得到正确的解决方案,当它得到正确的解决方案时,它将返回grid
,然后返回新的
。那么什么时候是:
# backtrack
return False
打电话给?我有一个更好的建议,而不是写在纸上。格式化代码以显示逻辑正在执行的操作的可视化表示。以下是一种方法: def打印计数器(val,msg): 打印“%s[%d]%s%”(“”*val,val,msg) def answer_solve_数独(__网格,计数器=0): res=检查数独(网格) 如果res为无或res为假: 返回res grid=copy.deepcopy(网格) 对于xrange(9)中的行: 对于X范围(9)中的列: 如果网格[行][列]==0: 对于X范围内的n(1,10): 网格[行][列]=n 打印计数器(计数器,测试:(行%d,列%d)=%d“%(行,列,n)) 新建=回答、解决、数独(网格、计数器+1) 如果new不是False: 打印计数器(计数器,“解答数独()解答:返回”) 还新 #回溯 打印计数器(计数器,“回溯”) 返回错误 打印计数器(计数器,**已解决!返回顶部**) 回流栅 从pprint导入pprint 解决方案=答案解决数独(简易网格) pprint(解决方案) 我所做的是创建一个小的打印机函数,它将打印一个数字,并将消息缩进那么多空格。然后,在您的
答案\u求解\u数独
中,我给了它一个默认的计数器值0,并始终将计数器+1传递给每个递归调用。这样,随着深度的增加,数量也会增加。我把打印机的功能放在一起,以直观地说明正在发生的事情
您将看到如下内容:
# backtrack
return False
仅当解算器找到解决方案时,才会调用return new,
这将在返回网格后立即调用
是的,当对answer\u solve\u sudoku
的调用通过整个循环而没有失败并到达底部时,它已经成功并返回网格。然后调用方将得到该网格作为new=answer\u solve\u sudoku(网格)
的结果,并返回该结果。网格将备份堆栈上的每个返回调用
回溯何时发生
因为您在每个递归中创建网格的副本,除非该步骤找到解决方案,否则它对该网格所做的更改将被丢弃,因为一旦我们返回一个步骤,我们将返回到以前的网格状态。它尝试使用该解决方案尽可能多地运行,直到超过值9 你应该看看这个。它有用于递归回溯的伪代码和实际代码。代码是用Java编写的,但它与Python的思维过程相同。更容易看到回溯如何处理较小的问题。。像4个皇后。。。看看奇怪的巧合。。。两天前刚刚回答:,相同的主题,相同的函数名。@jdi可能是因为:啊。是的,也许你们都在同一个班:-)你们可能已经在做这个了,但是当在纸上写东西的时候,逐行浏览程序是很有帮助的,以确保你们写的是程序在做什么,而不是你们认为它在做什么。我喜欢在白板上这样做,这样我就可以写出一个变量列表,并像程序一样更新它们的值。
[0] test: (row 0, col 2) = 1
[0] test: (row 0, col 2) = 2
[0] test: (row 0, col 2) = 3
[0] test: (row 0, col 2) = 4
[1] test: (row 0, col 3) = 1
[2] test: (row 0, col 4) = 1
[2] test: (row 0, col 4) = 2
[2] test: (row 0, col 4) = 3
...
[45] test: (row 7, col 7) = 8
[45] test: (row 7, col 7) = 9
[45] backtrack
[44] test: (row 7, col 5) = 6
[44] test: (row 7, col 5) = 7
...
[51] test: (row 8, col 6) = 6
[51] test: (row 8, col 6) = 7
[52] **SOLVED! Returning back up to top**
[51] answer_solve_sudoku() solved: returning
[50] answer_solve_sudoku() solved: returning
[49] answer_solve_sudoku() solved: returning
...
[2] answer_solve_sudoku() solved: returning
[1] answer_solve_sudoku() solved: returning
[0] answer_solve_sudoku() solved: returning