函数式编程Python:最小的数字可以被1到20的每个数字整除

时间:2017-11-16 13:22:16

标签: python recursion functional-programming

我想使用其函数编程功能在python中构建一个while循环,但直到现在我都失败了。

我所取得的成就是代码的平衡,它应该计算出每个数字1到20可被整除的最小数字。但它似乎并没有使用函数编程功能。并且还给出了如下错误:

  

“runtimeError:超出”的最大递归深度“在”i“的增量行;

即使这应该限制在20个。

def byYmult(x, y): return x % y == 0
def first20div():
    i=0
    for y in range(1,20):
        i += byYmult(x, y)
    return i >= 20

def while_block():
    global x
    if first20div(): 
        print(x)
        return 1
    else:
        x += 1
    return 0

x = 0
while_FP = lambda: ((not first20div()) and while_block() ) or while_FP()
while_FP() 

1 个答案:

答案 0 :(得分:5)

由于很多原因,这是非功能性的:

  1. 你没有通过,也没有返回功能;
  2. 你只在底部构建一个名为lambda的表达式,但这通常被认为是 un-Pythonic ;
  3. 通常函数式编程意味着您不会更改数据,但在此定义global x,您需要更新;
  4. 某些全局变量的
  5. 也被视为无功能:所有数据都应该传递给函数。
  6. 所以有很多工作要做。此外,您描述的算法不是非常优化。我们不断执行蛮力方法,直到最后我们仍然幸运地猜测数字,更好的方法是计算数字1..20的最小公倍数(LCM)

    我们可以首先定义 - 以功能方式 - 我们可以通过首先计算最大公共分频器(GCD)来计算LCM,这可以通过Euclidean Algorithm来完成。幸运的是,它已经在math包中了:

    from math import gcd
    

    现在LCM是:

    def lcm(a,b):
        return (a*b)//gcd(a,b)
    

    三个或更多个数字的最小公倍数可以通过计算前两个数字的最小公倍数来计算,然后将其作为第一个参数传递给具有第三个数字的最小公倍数,或者更正式地:

    lcm(x,y,z) == lcm(lcm(x,y),z)
    

    可以使用reduce中的functools

    来完成此操作
    from functools import reduce
    
    def lcm_multiple(xs):
        return reduce(lcm, xs)
    

    现在我们可以通过传递range(2,20)对象来计算答案:

    answer = lcm_multiple(range(2, 20))
    

    或完整:

    from math import gcd
    from functools import reduce
    
    def lcm(a,b):
        return (a*b)//gcd(a,b)
    
    def lcm_multiple(xs):
        return reduce(lcm, xs)
    
    answer = lcm_multiple(range(2, 20))