我目前正在介绍Python和计算理论课,最近有一个关于中期的难题,我根本无法解决。它涉及为添加数字的程序编写代码。我相信这个问题应该使用递归。我不记得问题究竟是如何措辞的,但这是基本的想法。
实现multiadder(n)
函数,该函数接收非负整数n
并将n
个任意值加在一起。要添加的每个值必须作为单独的调用写入。例如:
>>> multi_three = multiadder(3)
>>> multi_three(1)(2)(3)
6
>>> multiadder(5)(1)(2)(3)(4)(5)
15
必须填写空白来编写代码。
def multiadder(n):
assert n > 0
if _________________________ :
return _________________________
else:
return _________________________
我们在课堂上讨论的主题是高阶函数,递归,lambdas和控制语句。我们不允许使用像列表和集合这样的数据结构,也不允许我们导入任何内容。
有人请帮忙。这是我无法进行测试的唯一问题!
答案 0 :(得分:34)
试试这个:
def multiadder(n):
assert n > 0
if n == 1:
return lambda t: t
else:
return lambda a: lambda b: multiadder(n-1)(a+b)
if __name__ == '__main__':
print(multiadder(5)(1)(2)(3)(4)(5))
对于n == 1
,结果必须是返回输入的函数。
对于n > 1
,请通过添加输入来包装n-1
的结果。
这也适用于连接字符串和其他累积操作:
>>> multiadder(3)('p')('q')('r')
pqr
答案 1 :(得分:5)
你可以这样做,但它几乎是不可读的。我希望这些解释很有帮助:
def multiadder(n):
assert n > 0
if n == 0:
return 0
else:
return (lambda f: lambda i, n, sm: f(f, i, n, sm))(
lambda rec, i, n, sm: sm+i if n == 0 else lambda j: rec(rec, j, n-1, sm+i)
)(0, n, 0)
返回值由三个主要部分组成:
(lambda f: lambda i, n, sm: f(f, i, n, sm))
简而言之,此函数为函数指定名称,因此可以递归调用它。更详细:
它需要一个函数f
,它必须自己接受4个参数,其中第一个应该是自引用。
此处返回的函数接受另外三个参数,并返回f
的递归调用。
第二部分是真正的核心:
(lambda rec, i, n, sm: sm+i if n == 0 else lambda j: rec(rec, j, n-1, sm+i))
这作为参数传递给上面的第一个函数,使递归成为可能。 该函数采用上面提到的4个参数,并应用特定的逻辑:
i
是必须添加的号码n
是在此sm
是到目前为止的累计金额(不包括i
)根据是否需要更多值,此函数返回最终结果(sm+i
)或
一个带有一个参数的函数,它将执行与此处描述的相同(递归),减少n
,并使用自适应的总和。
最后,初始值传递给上面的内容:
(0, n, 0)
意思是,我们从数字0(虚拟),n
期望值和当前总和0开始。
由于上述代码中的递归不涉及对multiladder
的调用,并且断言确实将if
条件排除为真,我们可以不使用if...else
:< / p>
def multiadder(n):
assert n > 0
return (lambda f: lambda i, n, sm: f(f, i, n, sm))(
lambda rec, i, n, sm: sm+i if n == 0 else lambda j: rec(rec, j, n-1, sm+i)
)(0, n, 0)
答案 2 :(得分:3)
您还可以定义一个内部辅助函数(loop
),它跟踪计数状态(acc
)递减时的总和状态(n
)
def multiadder(n):
def loop(acc,n):
if n == 0:
return acc
else:
return lambda x: loop(acc+x, n-1)
return loop(0,n)
print(multiadder(3)(1)(2)(3)) # 6
print(multiadder(5)(1)(2)(3)(4)(5)) # 15
它不像DarkKnight的回答那么优雅,但初学者可能更容易概念化。事实上,这种模式是非常有用和多功能的,我用它来定义几乎所有的递归过程。
def some_recursive_func:
def loop(...state_parameters):
if base_condition:
return answer
else:
return loop(...updated_state_variables)
return loop(...initial_state_variables)
我们对此模式的唯一修改是将if
表达式的递归分支包含在lambda x: ...
中 - 这是因为multiadd
意味着返回函数直到{{1}已经应用了返回的函数。
还有一个,只是为了使用传奇的Y-combinator来获得乐趣。这可能不符合教练提供的标准,但看到它很酷。 Multiline lambdas in python are not really a thing所以可读性受到了一点影响。
n
如果您需要
,或者您仍然可以使用U = lambda f: f(f)
Y = U (lambda h: lambda f: f (lambda x: h (h) (f) (x)))
multiadder = Y (lambda f: lambda acc: lambda n:
acc if n == 0 else lambda x: f (acc+x) (n-1)
) (0)
print(multiadder(3)(1)(2)(3)) # 6
print(multiadder(5)(1)(2)(3)(4)(5)) # 15
语法定义multiadder
def
它的工作方式相同。
我强烈建议您逐步跟踪评估,以了解其运作方式。在理解这些高阶函数时,可以获得一些巨大的见解。
答案 3 :(得分:-2)
起初似乎很喜欢多个人需要两个输入才能工作,但答案非常简单。我不会想到#&#34; Python简介&#34; class需要lamba函数等等。
这是最终答案:
def multiadder(n):
assert n > 0
if n == 1:
return 1
else:
return n + multiadder(n - 1)
下图解释了它如何适用于n = 4:
multiadder(4)
|
return 4 + multiadder(3)
|
return 3 + multiadder(2)
|
return 2 + multiadder(1)
|
return 1
因此,n = 4的最终结果最终为4 + 3 + 2 + 1 = 10.