[英]Modifying a set within a recursive function?
我正在尝试编写一个程序来检查是否可以使用给定的“boggle board”来制作特定的单词。 挑战的完整细节在这里: Boggle Word Checker 。
基本上,该程序应该在板上找到单词的第一个字母,然后检查板上的任何相邻字母是否与该单词的下一个字母匹配。
这是我到目前为止所得到的(我不太清楚):
def pos(board, x, y):
# function to get value from a grid, but return None if not on grid,to
# prevent wraparound
if x >= 0 and y >= 0 and x < len(board[0]) and y < len(board):
return board[y][x]
else:
return None
def surrounds(board, x, y):
# make a dictionary which to store the positions and values of adjacent
# letters on board, given a single postision as input
return {
(x-1,y-1) : pos(board,x-1,y-1), #aboveLeft
(x,y-1) : pos(board,x,y-1), #aboveMiddle etc...
(x+1,y-1) : pos(board,x+1,y-1),
(x-1,y) : pos(board,x-1,y),
(x+1,y) : pos(board,x+1,y),
(x-1,y+1) : pos(board,x-1,y+1),
(x,y+1) : pos(board,x,y+1),
(x+1,y+1) : pos(board,x+1,y+1)
}
def find_word(board, word):
# initialise
listOfCoords = []
# find all occurrences of the first letter, and store their board
# position in a list
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == word[0]:
listOfCoords.append([j,i])
print('list of ' + word[0] + 's on board:')
print(listOfCoords)
print()
# if word is only 1 letter long then we can return True at this point
if listOfCoords and len(word) == 1:
return True
# otherwise we move on to look for the second letter
return findnext(board,word,listOfCoords)
def findnext(board, word, mylist):
for x, y in mylist:
print("Current coords: {},{}\n".format(x,y))
surroundings = surrounds(board,x,y)
listFounds = []
for k, v in surroundings.items():
if v == word[1]:
print("{} found at {}".format(v,k))
print()
if len(word) == 2:
print()
return True
listFounds.append(k)
if findnext(board, word[1:], listFounds) == True:
return True
return False
testBoard = [
["E","A","R","A"],
["N","L","E","C"],
["I","A","I","S"],
["B","Y","O","R"]
]
print(find_word(testBoard, "CEREAL"))
但是,我遇到了一个问题,因为挑战指定板上没有 position 可以多次使用。 因此,在上面的示例中,程序应该为“CEREAL”返回 False,但我的返回 True。
我在想解决这个问题的方法是使用一个集合,一旦找到下一个字母,它就会将坐标添加到集合中。 但是,对于需要在哪里创建空集,以及它将如何与所有循环和递归一起工作,我有点迷茫......
例如,假设我们在另一块板上寻找“CEREAL”,它有 2 个 E 与 C 相邻。 假设第一条路径只通向 CER,另一条通向 CEREAL。 如果我们首先沿着 CER 路径 go,它的位置将被添加到集合中,并且我需要在它沿着 CEREAL 路径之前再次删除它们。
我正在努力思考如何在我的程序中实现这一点。
您需要将一个布尔值数组设置为棋盘大小,全部设置为 False。 当您使用字母并递归调用 function 时,请将所用字母的单元格设置为 True。 从递归调用返回时,将单元格值设置回 False。 您应该只使用带有 False 值的字母,表明它们以前没有被使用过。
或者,您可以在将字母保存在临时变量中之后用 None 替换使用的字母,然后进行递归调用。 从递归调用返回后,从 temp 变量中放回单元格的值。
脚步:
该解决方案也适用于NxM
板。
def is_within_bounds(row, col, row_dim, col_dim):
return row >= 0 and row < row_dim and col >= 0 and col < col_dim
def get_neighbors(row, col, row_dim, col_dim):
for r_offset in (-1, 0, 1):
for c_offset in (-1, 0, 1):
if r_offset == 0 and c_offset == 0:
continue
r_new = row + r_offset
c_new = col + c_offset
if is_within_bounds(r_new, c_new, row_dim, col_dim):
yield (r_new, c_new)
def is_word_found(board, word, row, col, visited):
if word[0] != board[row][col]:
return False
if len(word) == 1:
return True
for neighbor in get_neighbors(row, col, len(board), len(board[0])):
if neighbor not in visited:
visited.add(neighbor)
if is_word_found(board, word[1:], neighbor[0], neighbor[1], visited):
return True
visited.remove(neighbor)
return False
def find_word(board, word):
for row in range(len(board)):
for col in range(len(board[0])):
if word[0] != board[row][col]:
continue
if is_word_found(board, word, row, col, set()):
return True
return False
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.