我想知道是否有人能够告诉我这个程序是如何得出正确答案的。我试图追踪它并且不确定去哪里因为它有一个or
,所以我很困惑,应该如何跟踪它。谢谢你的任何澄清。
编写一个功能分区,其中包含数字xs
列表,起始位置i
和所需总和s
并返回True
或False
取决于是否有可能从位置i
开始查找列表元素的子序列,其总和恰好为s
。请注意,始终可以生成总和为0的元素的子序列,即空元素序列。
def partition(xs,i,s):
print i,s
if i == len(xs):
return s == 0
else:
return partition(xs,i+1,s-xs[i]) or partition(xs,i+1,s)
答案 0 :(得分:3)
rcviz模块是一个很好的工具,可以帮助可视化递归函数:
边缘按执行遍历它们的顺序编号。 2.边缘从黑色变为灰色,表示遍历顺序:首先是黑色边缘,最后是灰色边缘。
如果您按照编号 1-11 的电话进行操作,您可以确切地看到发生了什么,i
从0
开始,然后转到1,2 3,最后4,左边的最后一个值是partitition([1,2,3,4],4,-2)
所以它为s == 0
返回False。
接下来我们回到i
2
然后再回到3,4,最后回到partitition([1,2,3,4],4,1)
,s == 1
再次False
。
接下来,我们从以6
结尾的步骤partitition([1,2,3,4],4,5)
开始,s == 0
再次为假。
最后在右侧,我们从partitition([1,2,3,4],4,7)
一直到partitition([1,2,3,4],4,0)
,其中s == 0
为True,函数返回True
。
如果您接听前四个电话,您可以看到流程如何以及如何更改。
partitition([1,2,3,4],1,7) # -> xs[i] = 1 s - 1 = 7
partitition([1,2,3,4],2,5) # -> xs[i] = 2 s - 2 = 5
partitition([1,2,3,4],2,5) # -> xs[i] = 3 s - 3 = 2
partitition([1,2,3,4],2,5) # -> xs[i] = 4 s - 4 = -2
s == 0 # -> False
答案 1 :(得分:2)
也许这个版本在逻辑上等同,使它更清晰一点。关键是return a or b
等同于if a: return a else: return b
。
def partition(xs,i,s):
print i,s
if i == len(xs):
# Base case: If the goal is to sum to 0, we succeed.
return s == 0
else:
# First, try including element i in our sum:
first_try = partition(xs,i+1,s-xs[i])
if first_try:
return True
else:
# If first try failed, try not including element i
second_try = partition(xs,i+1,s)
return second_try
答案 2 :(得分:0)
这是or
在这种情况下如何运作的解释:
return partition(xs,i+1,s-xs[i]) or partition(xs,i+1,s)
如果此表达式的计算结果为partition(xs,i+1,s-xs[i])
,将返回True
。如果partition(xs,i+1,s-xs[i])
评估为False
,则会返回partition(xs,i+1,s)
(无论评估为True
还是False
)。
请注意,您可以使用以下一组简单示例对此进行测试:
In [1]: 1 or 2 # When both are True, the first is returned.
Out[1]: 1
In [2]: 0 or 2 # When the first is False, the second is returned.
Out[2]: 2
In [4]: 0 or False # When both are False, the second is returned.
Out[4]: False
答案 3 :(得分:0)
我认为如果用更好的名字和没有索引编写它会变得容易多了:
def can_add_to(numbers, sumwanted):
if not numbers:
return sumwanted == 0
first, *rest = numbers
return can_add_to(rest, sumwanted-first) or can_add_to(rest, sumwanted)
print(can_add_to([1, 4, 9, 25], 13))
这和你的一样,只是更具可读性。然后说明:
如果没有数字,那么答案是"是"当且仅当所需金额为零时,我们可以马上说出来。
否则取第一个数字(和其余数字)。您可以将它用于总和。
使用它:can_add_to(rest, sumwanted-first)
告诉您剩余总和(减去first
之后)是否可以从其余数字中获得。
不使用它:can_add_to(rest, sumwanted-first)
告诉您整个总和是否可以仅由其余数字构成。
总体答案是"是"当且仅当您可以使用> >> first
来计算总和。这就是为什么你把两个子答案和or
放在一起的原因。