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

Nic*_*dio 1 python recursion functional-programming

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

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

在"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() 
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

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

  1. 你没有通过,也没有返回功能;
  2. 你只在底部构造一个名为lambda的表达式,但这通常被认为是非Pythonic ;
  3. 通常函数式编程意味着你不会改变数据,但在这里你定义一个global x,你更新;
  4. 一些全局变量也被视为无功能:所有数据都应该传递给函数.

所以有很多工作要做.此外,您描述的算法不是非常优化.我们不断采用蛮力方法来猜测数字,直到最后我们幸运,更好的方法是计算数字1..20的最小公倍数(LCM).

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

from math import gcd
Run Code Online (Sandbox Code Playgroud)

现在LCM是:

def lcm(a,b):
    return (a*b)//gcd(a,b)
Run Code Online (Sandbox Code Playgroud)

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

lcm(x,y,z) == lcm(lcm(x,y),z)
Run Code Online (Sandbox Code Playgroud)

这可以通过使用reducefrom 来完成functools:

from functools import reduce

def lcm_multiple(xs):
    return reduce(lcm, xs)
Run Code Online (Sandbox Code Playgroud)

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

answer = lcm_multiple(range(2, 20))
Run Code Online (Sandbox Code Playgroud)

或完整:

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))
Run Code Online (Sandbox Code Playgroud)