简体   繁体   English

在Python中将for循环转换为递归

[英]Converting a for loop to recursion in Python

I am new to recursion and am trying to convert a for loop to recursion. 我是递归的新手,正在尝试将for循环转换为递归。

allProducts = []

for a in range(10):
    for b in range(10):
        for c in range(10):
            for d in range(10):
                if (a*b*c*d)%6==0:
                    allProducts.append(a*b*c*d)

I am not able to convert this to a recursive program, which means I am not able to scale up. 我无法将其转换为递归程序,这意味着我无法扩大规模。 The idea is this - define a recursive program in Python that takes input A (number of for loops) and B (number which is a divisor of the product). 想法是这样的-在Python中定义一个递归程序,该程序接受输入A(for循环的数量)和B(该乘积的除数)。

Any help would be really helpful. 任何帮助都会非常有帮助。

You should have a look at the builtin package itertools : 您应该看看内置的软件包itertools

for a,b,c,d in itertools.product(range(10),range(10),range(10),range(10)):
    if (a*b*c*d)%6==0:
        allProducts.append(a*b*c*d)

You can use itertools.product and its repeat argument: 您可以使用itertools.product及其repeat参数:

from operator import mul
import itertools


def myprod(n, div, repeat=4):
    # i is a list of factors
    for i in itertools.product(range(n), repeat=repeat):
        # calculate product of all elements of list            
        prod = reduce(mul, i, 1)
        if prod % div == 0:
            yield prod

print list(myprod(10, 6))

Changing the repeat argument of myprod will change the number of loops and factors you are calculating. 更改myprodrepeat参数将更改您正在计算的循环数和因子。

Also, since multiplication is commutative ( a * b == b * a ) you should eliminate repetitive computations using itertools.combinations_with_replacement : 另外,由于乘法是可交换的( a * b == b * a ),因此应使用itertools.combinations_with_replacement消除重复计算:

from operator import mul
import itertools


def myprod_unique(n, div, repeat=4):
    for i in itertools.combinations_with_replacement(range(n), r=repeat):
        prod = reduce(mul, i, 1)
        if prod % div == 0:
            yield prod

print list(myprod_unique(10, 6))

If you remove duplicate results from myprod using set you will find that the two results are equal: 如果使用setmyprod删除重复的结果,则会发现两个结果相等:

print set(myprod_unique(10, 6)) == set(myprod(10, 6))

but you have cut down the number of operations drastically from n ** r to (n+r-1)! / r! / (n-1)! 但您已将运算次数从n ** r大大减少到(n+r-1)! / r! / (n-1)! (n+r-1)! / r! / (n-1)! . For example 92,378 instead of 10,000,000,000 for n=10, r=10 . 例如,对于n=10, r=10 92,378代替10,000,000,000。

The other answers don't use recursion. 其他答案不使用递归。 For completeness, here is one that does. 为了完整起见,以下是一种方法。

Recursive functions usually have two parts. 递归函数通常包含两个部分。

  • Base case: Handled directly. 基本情况:直接处理。 Corresponds to the body of the innermost loop in your code. 对应于代码中最里面的循环的主体。

  • Recursive case: Involves calling the function again, corresponds to one for loop in your code. 递归的情况:涉及再次调用该函数,对应于代码中的一个for循环。

Sometimes extra parameters need to be introduced. 有时需要引入额外的参数。 In this example the variables a , b , etc. that have already been set need to be passed in. The natural way to do that is using a list. 在此示例中,需要传入已经设置的变量ab等。完成此操作的自然方法是使用列表。

allProducts = []

def product(vals):
    res = 1
    for val in vals:
        res *= val
    return res

# n is the number of for loops remaining
# mod is the divisor
# vals is a list where the values of a, b, c, etc. will be placed
# start this function off using run(4, 6, [])
def run(n, mod, vals):
    if n == 0:
        # base case
        if product(vals) % mod == 0:
            allProducts.append(product(vals))
    else:
        # recursive case
        for i in range(10):
            # i takes the role of a, b, c, etc.
            # add i to the vals
            vals.append(i)
            # recursively iterate over remaining n-1 variables
            run(n - 1, mod, vals)
            # remove i
            vals.pop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM