【问题标题】:Undetermined number of for loops depending on one parameter取决于一个参数的未确定数量的 for 循环
【发布时间】:2014-05-27 17:45:59
【问题描述】:

我正在尝试执行以下操作:一个函数接收两个数字 n 和 d,其中 n 是循环迭代的次数,d 是一个参数,它确定循环限制的方式是对数字数组执行某些操作[a_1,...,a_n] 对于所有正的 a_1,...,a_n 使得它们总和为 d。例如,如果 n=4,它应该执行以下操作:

for i in range (0,d+1):
    for j in range(0,d+1-i):
        for k in range(0,d+1-i-j):
            doSomething([i, j, k, d-i-j-k])

我从this question 和几年前的编程知识中收集到,这应该使用递归函数来完成。不幸的是,我不太清楚应该如何传递参数(我已经有几年没有编程了,我有点生疏了)。

【问题讨论】:

    标签: python for-loop recursion nested-loops


    【解决方案1】:

    这是一个递归解决方案:

    def drill(f, n, d, items=()):
        if n > 1:
            for i in range(d+1):
                drill(f, n-1, d-i, items+(i,))
        else:
            f(list(items) + [d])
    

    ...这样称呼:

    >>> def p(x): print x
    ...
    >>> drill(p, 3, 4)
    [0, 0, 4]
    [0, 1, 3]
    [0, 2, 2]
    [0, 3, 1]
    [0, 4, 0]
    [1, 0, 3]
    [1, 1, 2]
    [1, 2, 1]
    [1, 3, 0]
    [2, 0, 2]
    [2, 1, 1]
    [2, 2, 0]
    [3, 0, 1]
    [3, 1, 0]
    [4, 0, 0]
    

    【讨论】:

    • 啊,那你使用的是 Python 2.x(其中print 是一个语句而不是一个函数)......一会儿......
    • ... 现已为 Python 2.x 修复。
    • 是的,你是对的。我以为我在使用 3。也许我应该使用 3。
    • Python 2 是 supported until 2020(还有一些第三方库尚未移植到 Python 3),但是 Python 3 可以让您编写更好的代码 IMO - print 作为一个函数一个很好的例子。
    • 如果你刚刚开始,那么尽可能使用 python 3 是一个好点,而不是依赖于那些只为 python 2 提供的旧库。
    【解决方案2】:

    您当然可以使用递归,但也可以只使用 itertools (https://docs.python.org/2/library/itertools.html):

    import itertools
    
    def call_on_sum_permutations(callable, n, d):
        for a in itertools.product(range(d+1),repeat=n):
            if sum(a) == d:
                callable(a)
    
    def pr(x):
        print(x)
    
    call_on_sum_permutations(pr, 3, 10)
    

    如果 n 很大,这可能会变得笨拙

    (另请注意,您的描述说 a_1 对 a_n 是肯定的,但您的代码允许零,所以我也这样做了。您可能还会发现值得查看该模块中的 itertools.permutations、itertools.combinations 和其他内容)

    【讨论】:

    • 谢谢。我想过做这样的事情(事实上这是我到目前为止已经实现的,也许我应该提到它)但是我会通过不需要调用的实例进行多次迭代(即当 sum(a)! =n)。另一方面,如果我使用递归,我会增加创建多个堆栈的低效率。在您看来,什么会更有效?
    • 由于您陈述的原因,当 n 很大时,递归将显着提高效率。否则,它可能不会有太大的不同,特别是如果 doSomething 是一个足够大的任务。
    • 谢谢!我打算让 n 长,所以我想我会去递归。
    猜你喜欢
    • 1970-01-01
    • 2022-11-26
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2012-11-23
    • 1970-01-01
    相关资源
    最近更新 更多