Python 递归错误-分离度
我试图在电影数据库中找到任何两个演员之间的分离程度。 当我达到我的基本情况时,我成功了,即1个分离度(即演员与另一个演员在同一部电影中),但我使用递归查找所有其他分离度,我得到: 我使用的文本文件可以在 为了测试基本情况,我使用:Python 递归错误-分离度,python,database,recursion,Python,Database,Recursion,我试图在电影数据库中找到任何两个演员之间的分离程度。 当我达到我的基本情况时,我成功了,即1个分离度(即演员与另一个演员在同一部电影中),但我使用递归查找所有其他分离度,我得到: 我使用的文本文件可以在 为了测试基本情况,我使用:Bacon,Kevin和Pitt,Brad 为了测试其他人,我使用了Bacon、Kevin和Gamble、Nathan除非actedWith的某些属性我没有看到,否则你没有任何东西可以阻止无限循环。例如,您的一个递归调用将是getDegrees(“Gamble,Nath
Bacon,Kevin
和Pitt,Brad
为了测试其他人,我使用了
Bacon、Kevin
和Gamble、Nathan
除非actedWith的某些属性我没有看到,否则你没有任何东西可以阻止无限循环。例如,您的一个递归调用将是getDegrees(“Gamble,Nathan”,“Pitt,Brad”,2)
,然后由于Kevin Bacon与Brad Pitt合作过,当您更深入一层时,您将调用getDegrees(“Gamble,Nathan”,“Bacon,Kevin”,3)
。看到问题了吗 可能是无限递归。你正在搜索一棵扎根在目标上的树;树上的一些路径到达了它们上游的点。你需要一种方法来认识到这一点,并在它发生时停止往下看
一种方法是在路径上保留祖先列表。比如:
def getDegrees(target, base, dos, ancestors): # Also carry a list of "ancestors"
for actor in actedWith[base]:
if target == actor:
print base, "has ", dos, " degree(s) of separation from ", target
return
dos = dos+1
ancestors = ancestors + [base] # Must be separate variable binding to avoid mutating the caller's copy
for actor in actedWith[base]:
if actor in ancestors: continue # Check if on path, skip if so
getDegrees(target, actor, dos, ancestors)
...
getDegrees(target, base, dos, [target])
请注意,“祖先”是指路径上的一个点,而不是参与者可能与之相关的人
这并不能避免这样的情况,即参与者使用自己进行了操作(希望输入文件永远不会包含该操作),但只需稍作更改即可。有两条建议(我没有查看文本文件,只是在这里介绍第一原则并快速阅读您的代码):
当您从getDegrees返回时,返回后仍将完成函数的其余部分。您需要返回一个True(或其他值)来指示搜索结束,并且应该回滚整个函数调用堆栈。第一个返回将更改为“return True”,最后一行将更改为“if getDegrees(target、actor、dos):return True”
跟踪哪些演员已经被搜查过。如果两个参与者彼此合作,或者在关系中存在循环,则会来回循环李>
这段代码试图修复返回和图形周期问题。然而,在某些地方仍然存在逻辑错误;Kevin Bacon和James Belushi(分离度为2)给出了以下结论:
约瑟夫·瑟拉沃(Siravo,Joseph)与詹姆斯·贝卢斯(Belushi,James)有179个分离学位
编辑:通过添加“原始”参数进行修复
但是递归问题是固定的
##gets file with movie information
f = open("filename.txt")
actedWith = {}
ActorList = []
movies = {}
actedIn = []
dos = 1
def getDegrees(original, target, base, dos=0, seen=[]):
dos = dos+1
print "----> checking %s against %s" % (target, base)
for actor in actedWith[base]:
#print "\t" + actor
if target == actor:
print original, "has ", dos, " degree(s) of separation from ", target
return True
for actor in actedWith[base]:
if actor in seen: continue
seen = seen + [actor]
if getDegrees(original, target, actor, dos, seen):
return True
return False
for l in f:
##strip of whitespace
l = l.strip()
##split by where forward-slashes are
l = l.split("/")
##add the first "word" on the line to the database of movie names
movies = {l[0] : l[1:]}
for e in l[1:]:
if e in actedWith:
actedWith[e] = actedWith[e]+movies[l[0]]
else:
actedWith[e] = movies[l[0]]
original = raw_input("Enter Actor Name (Last, First): ")
target = raw_input("Enter Second Actor Name (Last, First): ")
getDegrees(original, target, original)
例如:
Bacon, Kevin has 65 degree(s) of separation from Kosaka, Masami
我试着实现了这一点……但是,我仍然得到相同的错误。@RMartin此代码不正确;它不会将祖先传递给getDegrees递归,也不会修复返回问题。啊,没错。问题是我懒得运行它。不……不幸的是,递归问题仍然存在。我输入了一组不同的演员:培根、凯文和小坂、马萨米。同样的递归错误。返回不同名称的错误是由“print base”、“has”、“dos”、“degrees of separation from”、“target”引起的。通过创建一个新变量来存储原始基,问题得到解决,但计数度的逻辑错误仍然存在。@RMartin请检查您的实现。我刚测试过这个名字,效果很好。很抱歉…试试约翰逊,切丽。我只是复制/粘贴您的代码以确保;它似乎搜索了其中的许多,然后返回运行时错误。
##gets file with movie information
f = open("filename.txt")
actedWith = {}
ActorList = []
movies = {}
actedIn = []
dos = 1
def getDegrees(original, target, base, dos=0, seen=[]):
dos = dos+1
print "----> checking %s against %s" % (target, base)
for actor in actedWith[base]:
#print "\t" + actor
if target == actor:
print original, "has ", dos, " degree(s) of separation from ", target
return True
for actor in actedWith[base]:
if actor in seen: continue
seen = seen + [actor]
if getDegrees(original, target, actor, dos, seen):
return True
return False
for l in f:
##strip of whitespace
l = l.strip()
##split by where forward-slashes are
l = l.split("/")
##add the first "word" on the line to the database of movie names
movies = {l[0] : l[1:]}
for e in l[1:]:
if e in actedWith:
actedWith[e] = actedWith[e]+movies[l[0]]
else:
actedWith[e] = movies[l[0]]
original = raw_input("Enter Actor Name (Last, First): ")
target = raw_input("Enter Second Actor Name (Last, First): ")
getDegrees(original, target, original)
Bacon, Kevin has 65 degree(s) of separation from Kosaka, Masami