Python递归挑战

时间:2016-09-17 08:22:58

标签: python recursion functional-programming

我目前正在介绍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和控制语句。我们不允许使用像列表和集合这样的数据结构,也不允许我们导入任何内容。

有人请帮忙。这是我无法进行测试的唯一问题!

4 个答案:

答案 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)

enter image description here上看到它。

如何运作

返回值由三个主要部分组成:

(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.