【问题标题】:Is it possible to remove recursion from this function?是否可以从此函数中删除递归?
【发布时间】:2010-10-11 14:42:09
【问题描述】:

我一直在玩这个,只是看不到明显的解决方案。我想从 XinY_Go 函数中删除递归。

def XinY_Go(x,y,index,slots):
   if (y - index) == 1:
      slots[index] = x
      print slots
      slots[index] = 0
      return
   for i in range(x+1):
      slots[index] = x-i
      XinY_Go(x-(x-i), y, index + 1, slots)

def XinY(x,y):
   return XinY_Go(x,y,0,[0] * y)

该函数正在计算将 X 弹珠放入 Y 槽的方法数。这是一些示例输出:

>>> xy.XinY(1,2) [1, 0] [0, 1] >>> xy.XinY(2,3) [2, 0, 0] [1, 1, 0] [1, 0, 1] [0, 2, 0] [0, 1, 1] [0, 0, 2]

【问题讨论】:

  • 用如何进行转换的粗略草图更新我的答案。在此处发布,以便您在个人资料页面上收到通知。

标签: python recursion


【解决方案1】:

@Joel Coehoorn's suggestion 的简单实现如下:

def XinY_Stack(x, y):
    stack = [(x, 0, [0]*y)]
    while stack:
        x, index, slots = stack.pop()
        if (y - index) == 1:
            slots[index] = x
            print slots
            slots[index] = 0
        else:
            for i in range(x + 1):
                slots[index] = x-i
                stack.append((i, index + 1, slots[:]))

例子:

>>> XinY_Stack(2, 3)
[0, 0, 2]
[0, 1, 1]
[0, 2, 0]
[1, 0, 1]
[1, 1, 0]
[2, 0, 0]

基于itertools.product

def XinY_Product(nmarbles, nslots):
    return (slots
            for slots in product(xrange(nmarbles + 1), repeat=nslots)
            if sum(slots) == nmarbles) 

基于嵌套循环

def XinY_Iter(nmarbles, nslots):
    assert 0 < nslots < 22 # 22 -> too many statically nested blocks
    if nslots == 1: return iter([nmarbles])
    # generate code for iter solution
    TAB = "  "
    loopvars   = []
    stmt       = ["def f(n):\n"]
    for i in range(nslots - 1):
        var = "m%d" % i
        stmt += [TAB * (i + 1), "for %s in xrange(n - (%s)):\n"
                 % (var, '+'.join(loopvars) or 0)]
        loopvars.append(var)

    stmt += [TAB * (i + 2), "yield ", ','.join(loopvars),
             ', n - 1 - (', '+'.join(loopvars), ')\n']
    print ''.join(stmt)
    # exec the code within empty namespace
    ns = {}
    exec(''.join(stmt), ns, ns)
    return ns['f'](nmarbles + 1) 

例子:

>>> list(XinY_Product(2, 3))
[(0, 0, 2), (0, 1, 1), (0, 2, 0), (1, 0, 1), (1, 1, 0), (2, 0, 0)]
>>> list(XinY_Iter(2, 3))
def f(n):
  for m0 in xrange(n - (0)):
    for m1 in xrange(n - (m0)):
      yield m0,m1, n - 1 - (m0+m1)

[(0, 0, 2), (0, 1, 1), (0, 2, 0), (1, 0, 1), (1, 1, 0), (2, 0, 0)]

【讨论】:

  • 谢谢!现在似乎有点明显了。 :)
【解决方案2】:

我们认为递归的一切也可以认为是基于堆栈的问题,其中递归函数只是使用程序的调用堆栈,而不是创建一个单独的堆栈。这意味着任何递归函数都可以改用堆栈重写。

我不太了解python,无法为您提供实现,但这应该为您指明正确的方向。但简而言之,将函数的初始参数压入堆栈并添加一个循环,只要堆栈的大小大于零,该循环就会运行。每次循环迭代弹出一次,每次函数当前调用自身时推送。

【讨论】:

  • 是的。我意识到这一点,我很难弄清楚将什么放入堆栈以及何时放入堆栈。我想多考虑一下这个问题对我来说不会有什么坏处。 :)
  • 很久以前,我从河内的塔楼中删除了递归,注意到在任何给定点上每个塔楼的总和中有一个模式。根据启动磁盘的数量(奇数或偶数),您始终可以知道接下来要移动哪个磁盘。现在,如果我能找到我的笔记。
【解决方案3】:

看看这个创建所有排列的代码,我想我会相对简单地为你的问题实现类似的东西。

How to generate all permutations of a list in python?

【讨论】:

    猜你喜欢
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多