[英]How do I break out of this recursive loop?
我仍然是Python的新手,因此如果有任何不好的語法和邏輯,請忍受。 無論如何,我有一個函數正在嘗試清理(請不要花哨的動作)打破遞歸循環。 它是程序中的一個函數,遞歸地迭代1和0(請參見下面的輸入文件),並將相鄰的0標識為不同的子集。 我有一個稱為“ checkAllInOneDirection”的遞歸函數,該函數將循環遍歷每個位置,向右,向左,向上,向下位置檢查0。 (每次遞歸在4個方向中的每個方向上只向左/向左/向下)。
問題是由於某種原因,第三組的輸出應僅將0,9和0,10檢測為一個不同的組,但是當第二組檢測后在遞歸中跳出時,它將選擇[0,4]和[1] ,3]在第三組檢查開始時...有什么幫助嗎?
這是輸出[行,列]:
Distinct subset found : [[0, 0]]
Distinct subset found : [[0, 3], [0, 4], [1, 3], [0, 5], [1, 4], [1, 5]]
Distinct subset found : [[0, 9], [0, 4], [1, 3], [0, 10]]
正確的第三個子集應該僅是:
Distinct subset found : [[0, 9], [0, 10]]
這是一個示例輸入文件:
01100011100100000
11100011111111011
10011111101011011
這是該函數的一個片段,稱為“ checkAllInOneDirection”:
isItLast = checkLast(forBoo, bakBoo, upBoo, dwnBoo)
if isItLast:
for each in tempCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch=[]
for each in newCatch:
if not each in finalCatch:
finalCatch.append(each)
newCatch=[]
return finalCatch, newCatch, columnCount, rowCount, width, height, posToCheck, forBoo, bakBoo, upBoo, dwnBoo
else:
for each in tempCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch =[]
for each in newCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch.append(each)
newCatch = []
return checkAllInOneDirection(finalCatch,tempCatch,recursiveCount,newCatch, columnCount, rowCount, width, height, posToCheck, forBoo, bakBoo, upBoo, dwnBoo)
這是整個功能,希望它只是澄清一下,不要讓我的問題更令人困惑:
def checkAllInOneDirection(finalCatch,tempCatch,recursiveCount,newCatch, columnCount, rowCount, width, height, posToCheck, forBoo, bakBoo, upBoo, dwnBoo):
for each in range (0, len(tempCatch)):
posToCheck = posToCheckBak = posToCheckUp = posToCheckDwn = [tempCatch[each][0], tempCatch[each][1]]
newPosForward = checkForward(posToCheck, width)
if newPosForward != False:
tempLocale = locale[newPosForward[0]][newPosForward[1]]
elif newPosForward == False:
tempLocale = 1
if newPosForward != False and tempLocale ==0 and not newPosForward in finalCatch and not newPosForward in newCatch:
forVal = locale[newPosForward[0]][newPosForward[1]]
newCatch.append(newPosForward)
posToCheck = newPosForward
forBoo = True
elif newPosForward == False and tempLocale == 1 and not newPosForward in newCatch:
forBoo = False
newPosBackward = checkBackward(posToCheckBak)
if newPosBackward != False:
tempLocale = locale[newPosBackward[0]][newPosBackward[1]]
elif newPosBackward == False:
tempLocale = 1
if newPosBackward != False and tempLocale ==0 and not newPosBackward in finalCatch and not newPosBackward in newCatch:
forVal = locale[newPosBackward[0]][newPosBackward[1]]
newCatch.append(newPosBackward)
posToCheckBak = newPosBackward
bakBoo = True
elif newPosBackward == False and tempLocale == 1 and not newPosBackward in newCatch:
bakBoo = False
newPosUp = checkUpRow(posToCheckUp)
if newPosUp != False:
tempLocale = locale[newPosUp[0]][newPosUp[1]]
elif newPosUp == False:
tempLocale = 1
if newPosUp != False and tempLocale ==0 and not newPosUp in finalCatch and not newPosUp in newCatch:
forVal = locale[newPosUp[0]][newPosUp[1]]
newCatch.append(newPosUp)
posToCheckUp = newPosUp
upBoo = True
elif newPosUp == False and tempLocale == 1 and not newPosUp in newCatch:
upBoo = False
newPosDwn = checkDwnRow(posToCheckDwn, height)
if newPosDwn != False:
tempLocale = locale[newPosDwn[0]][newPosDwn[1]]
elif newPosDwn == False:
tempLocale = 1
if newPosDwn != False and tempLocale ==0 and not newPosDwn in finalCatch and not newPosDwn in newCatch:
forVal = locale[newPosDwn[0]][newPosDwn[1]]
newCatch.append(newPosDwn)
posToCheckDwn = newPosDwn
dwnBoo = True
elif newPosDwn == False and tempLocale == 1 and not newPosDwn in newCatch:
dwnBoo = False
isItLast = checkLast(forBoo, bakBoo, upBoo, dwnBoo)
if isItLast:
for each in tempCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch=[]
for each in newCatch:
if not each in finalCatch:
finalCatch.append(each)
newCatch=[]
return finalCatch, newCatch, columnCount, rowCount, width, height, posToCheck, forBoo, bakBoo, upBoo, dwnBoo
else:
for each in tempCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch =[]
for each in newCatch:
if not each in finalCatch:
finalCatch.append(each)
tempCatch.append(each)
newCatch = []
return checkAllInOneDirection(finalCatch,tempCatch,recursiveCount,newCatch, columnCount, rowCount, width, height, posToCheck, forBoo, bakBoo, upBoo, dwnBoo)
使用遞歸時,您實際上不應該使用“循環”和“中斷”之類的短語。 取而代之的是,將問題視為由在基本案例中變得無關緊要的類似子問題組成。
你一般的問題是要找到0
的旁邊,是其他0
的。 (順便說一下,這被稱為4向洪水填充 。)因此,較大的問題具有相同的子問題。 所有連接的0
的列表與以下各項的組合相同:
0
0
的列表0
0
的列表0
0
的列表0
0
的列表0
因此,在遞歸函數中的某處,您將獲得以下效果:
return [[y,x]] + getConnectedZeros(x+1, y) + getConnectedZeros(x-1, y) + getConnectedZeros(x, y+1) + getConnectedZeros(x, y-1)
知道了這一點,您需要考慮一下基本情況,即getConnectedZeros()
必須返回與其子問題的解決方案組合不同的東西的情況。 對我而言,基本案例是:
1
的地方調用該函數時 0
上調用該函數時 在這兩種情況下,簡單地返回一個空列表都是可行的,因為當返回[]
時,它代替了更多的遞歸調用。 如果不包括這些條件,則遞歸將永遠運行,並且永遠不會 打破 打一個基本情況。
基於這些想法,這是您的問題的解決方案:
sampleInput = "01100011100100000\n11100011111111011\n10011111101011011"
inputMatrix = [[int(n) for n in row] for row in sampleInput.split('\n')] #matrix where each row is a list of the numbers from sampleInput
def getConnectedZeros(matrix, x, y, foundIndicies=[]):
if 0<=y<len(matrix) and 0<=x<len(matrix[y]): #catch out of bounds
if matrix[y][x] == 1: #catch 1s
return []
else:
if not (x,y) in foundIndicies: #catch 0's we've already "seen"
foundIndicies.append((x,y))
return [[y,x]] + getConnectedZeros(matrix, x+1, y, foundIndicies) + getConnectedZeros(matrix, x-1, y, foundIndicies) + getConnectedZeros(matrix, x, y+1, foundIndicies) + getConnectedZeros(matrix, x, y-1, foundIndicies)
else:
return []
else:
return []
#Now we can just loop through the inputMatrix and find all of the subsets
foundZeroIndicies = []
subsets = []
y = -1
for row in inputMatrix:
y += 1
x = -1
for val in row:
x += 1
if (not [y,x] in foundZeroIndicies) and val==0:
zerosList = getConnectedZeros(inputMatrix, x, y)
subsets.append(zerosList)
foundZeroIndicies.extend(zerosList)
for subset in subsets:
print "Distinct Subset Found : ", subset
希望對您有所幫助。 (希望它是連貫的,現在是凌晨5點...)
我的代碼是使用遞歸函數walk()的示例。 我希望它可以幫助您解決問題。
input = ['01100011100100000',
'11100011111111011',
'10011111101011011']
col_len = 17
row_len = 3
walked = []
output = []
def walk(subset_in, row, col):
if (0 <= row < row_len) and (0 <= col < col_len) and (row, col) not in walked:
walked.append((row, col))
if input[row][col] == '0':
if subset_in is not None:
subset = subset_in
else:
subset = []
subset.append((row, col))
walk(subset, row, col+1)
walk(subset, row+1, col)
walk(subset, row, col-1)
walk(subset, row-1, col)
if subset_in is None:
output.append(subset)
for row in xrange(row_len):
for col in xrange(col_len):
if (row, col) not in walked:
walk(None, row, col)
for subset in output: print subset
要打破遞歸,您需要使用return。 如果遞歸繼續進行,則需要重新考慮基本情況。
只是為了好玩,我嘗試使用networkx來實現,而不是它回答了您的問題:
data = """01100011100100000
11100011111111011
10011111101011011""".splitlines()
import networkx
G = networkx.Graph()
found = set()
for i, row in enumerate(data):
for j, c in enumerate(row):
if c == '0':
found.add((i, j))
if i + 1 < len(data) and data[i + 1][j] == '0':
G.add_edge((i, j), (i + 1, j))
if j + 1 < len(row) and row[j + 1] == '0':
G.add_edge((i, j), (i, j + 1))
groups = map(list, networkx.connected_component_subgraphs(G))
group_nodes = set(node for group in groups for node in group)
individuals = found - group_nodes
print groups
print individuals
"""
[[(0, 15), (0, 14), (1, 14), (0, 13), (0, 12), (0, 16), (2, 14)], [(1, 3), (1, 4), (1, 5), (0, 5), (0, 4), (0, 3)], [(2, 1), (2, 2)], [(0, 9), (0, 10)]]
set([(0, 0), (2, 11), (2, 9)])
"""
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.