回溯如何在 Python 中工作
Posted
技术标签:
【中文标题】回溯如何在 Python 中工作【英文标题】:How Backtracking works in Python 【发布时间】:2020-02-24 08:48:58 【问题描述】:我想出了这段从 Youtube 学习的代码。我使用它通过执行回溯来解决数独问题。
import pandas as pd
import numpy as np
raw = pd.read_csv(r'C:\Users\Administrator\Dropbox\Python_Learning\debaisudoku.csv', header = None)
sudoku = np.nan_to_num(raw)
def possible(x,y,n):
# global sudoku
for i in range(0,9):
if sudoku[i][y] == n:
return False
for i in range(0,9):
if sudoku[x][i] == n:
return False
x0 = (x//3) * 3
y0 = (y//3) * 3
for i in range(0,3):
for j in range(0,3):
if sudoku[x0+i][y0+j] == n:
return False
return True
def solve():
# global sudoku
for x in range(9):
for y in range(9):
if sudoku[x][y] == 0:
for n in range(1,10):
if possible(x,y,n):
sudoku[x][y] = n
if solve(): return True
sudoku[x][y] = 0
return False
print(sudoku)
solve()
一切都很好,除了这几行代码,我理解了代码:
if possible(x,y,n):
sudoku[x][y] = n
if solve(): return True
sudoku[x][y] = 0
return False
Python 如何运行、循环和记住位置然后继续计算上次使用的数字?顺便说一句,如果可能的话,请告诉我如何在 VBA 中执行回溯。我已经尝试使用 if 条件进行 goto,但没有任何效果。
非常感谢,感谢您的任何回答。
【问题讨论】:
这就是递归的全部原理。见this、this、this .... 当函数返回时(例如return False
),执行返回给调用者。来电者是您拥有solve()
的地方。如果返回值为 False,则以 solve
为条件的 if
块将不会被执行,因此使用 sudoku[x][y] = 0
和 执行继续(不重新启动)剩下的 for
循环的迭代在那里......
零只是与“移动”相对应的“撤消”动作,显然没有通过递归调用带来解决方案(因为它返回 False)。 for
循环的下一次迭代对于尝试替代“移动”是必要的,再次启动递归调用。如果该调用也返回 False,并且循环没有更多的迭代,那么该函数执行也将返回 False 给它自己的调用者。
它不会向后循环。但是要意识到函数solve
的每次递归执行都有自己的变量和执行上下文。因此,如果您进行递归调用,该调用将从一开始就执行其自己的for
循环。如果它执行return
,您将回溯到该函数的另一个实例,即进行递归调用的那个实例。 那个正在循环中,因此它继续从它在进行递归调用之前的位置开始循环。不要混淆不同的循环:递归树的每一层都有一个。
是的,我想你明白了。
【参考方案1】:
在 youtube 上看到电脑发烧友剧集后,我也一直在 VBA 中尝试它。
我想如果你想在 VBA 中“返回”,你需要使用“退出函数”功能。
当我在 Excel 表格中使用前 9*9 单元格作为网格时,此代码对我有用,在确认消息框后数独将自行重置,我不知道为什么会发生这种情况。
如果有人知道更简洁的编码方式,我会很高兴知道,希望对你有所帮助!
Function possible(y, x, n) As Boolean
For i = 1 To 9
If Cells(y, i) = n Then
possible = False
Exit Function
End If
Next i
For i = 1 To 9
If Cells(i, x) = n Then
possible = False
Exit Function
End If
Next i
x0 = ((x - 1) \ 3) * 3
y0 = ((y - 1) \ 3) * 3
For i = 1 To 3
For j = 1 To 3
If Cells(y0 + i, x0 + j) = n Then
possible = False
Exit Function
End If
Next j
Next i
possible = True
End Function
Function solve()
For y = 1 To 9
For x = 1 To 9
If Cells(y, x).Value = 0 Then
For n = 1 To 10
Debug.Print (n)
If n = 10 Then
Exit Function
End If
If possible(y, x, n) = True Then
Cells(y, x).Value = n
solve
Cells(y, x).Value = 0
End If
Next n
End If
Next x
Next y
MsgBox ("solved!")
End Function
Sub solve_sudoku()
solve
End Sub
【讨论】:
非常感谢。我会尽快测试它 确实有效。非常感谢你。这里的关键是退出函数以上是关于回溯如何在 Python 中工作的主要内容,如果未能解决你的问题,请参考以下文章
subprocess.Popen 管道如何在 Python 中工作?