确定递归调用是否没有解决方案

时间:2015-04-03 10:04:14

标签: python recursion

我们有以下递归算法,给出了给定金额的所有可能组合以达到某个目标。在另一个上下文中使用它,我想知道是否有办法明确宣布没有解决方案,而不是没有输出。

def purchase_possibilities(self, amounts, goal, current=[], highest=0, curr_sum=0, index=0):
    # See if we are done.
    if curr_sum == goal:
        self.display(current, amounts, index)
        return

    if curr_sum > goal:
        return

    for value in amounts:
        if value >= highest:
            # Copy the current list, then add the current value.
            copy = current[:]
            copy.append(value)
            # Recursively add more current.
            self.purchase_possibilities(amounts, goal, copy, value, curr_sum + value, index=index)

def display(self, current, amounts, index):
    # Display our combinations sorted by amount.
    for amount in amounts:
        count = current.count(amount)
        print("* -> " + self.get_product_name(amount, index), ":", count)
    print()

例如,如果我给出例如金额= [20,3,5,7.95]和目标= 28.79 我希望程序告诉我没有可能的组合来达到答案,而不是仅仅没有输出。

2 个答案:

答案 0 :(得分:1)

你可以使用一个标志并始终返回它,只有获得curr_sum == goal时才将其设置为True。

flag = [False]
def purchase_possibilities(amounts, goal, current=[], highest=0, curr_sum=0, index=0):
    # See if we are done.
    if curr_sum == goal:
        flag[0] = True
        return self.display(current, amounts)

    if curr_sum > goal:
        return []

    for value in amounts:
        if value >= highest:
            copy = current[:]
            copy.append(value)  
            # Copy the current list, then add the current value.
            # Recursively add more current.
            self.purchase_possibilities(amounts, goal, copy, value, curr_sum + value, index=index)
    return flag[0]

如果您想要留言,可以执行以下操作:

  return "No valid combination" if not flag[0]  else ""

另外在使用可变默认参数时,您可能最好将初始值设置为None并对标志执行相同操作,因为连续调用可能会提供不正确的输出:

def purchase_possibilities(amounts, goal, current=None, highest=0, curr_sum=0, index=0, flag=None):
    # See if we are done.
    if flag is None:
        flag = [False]
    if  current is None:
        current = []

将行更改为self.purchase_possibilities(amounts, goal, copy, value, curr_sum + value, index=index,flag=flag)

答案 1 :(得分:-1)

将递归方法重写为此应该非常简单;您有两个输入可用:金额列表和目标。没有解决方案可以通过空列表表示,可以用Pythonic方式测试"如果不是"

from itertools import *

# given a list, produce a generator which yields all possible
# subsets of the list
def allsubsets(l):
    for s in chain( *map(lambda r: combinations(l,r), xrange(len(l))) ):
        yield s
# filter the subsets whose sum is equal to the amount
goal_finder = lambda goal, amounts: \
                filter(lambda subset: sum(subset)==goal, allsubsets(amounts))

print goal_finder(29.75, [10,20,9,0.75])

输出:

[(20, 9, 0.75)]