我一直在玩这个,但是看不出明显的解决方案.我想从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]
Joel Coehoor.. 21
我们认为作为递归的所有东西也可以被认为是基于堆栈的问题,其中递归函数只使用程序的调用堆栈而不是创建单独的堆栈.这意味着可以使用堆栈重写任何递归函数.
我不太了解python给你一个实现,但这应该指向你正确的方向.但简而言之,将函数的初始参数推送到堆栈并添加一个循环,只要堆栈的大小大于零就会运行.每次循环迭代弹出一次,每次函数当前调用自身时都按下.
我们认为作为递归的所有东西也可以被认为是基于堆栈的问题,其中递归函数只使用程序的调用堆栈而不是创建单独的堆栈.这意味着可以使用堆栈重写任何递归函数.
我不太了解python给你一个实现,但这应该指向你正确的方向.但简而言之,将函数的初始参数推送到堆栈并添加一个循环,只要堆栈的大小大于零就会运行.每次循环迭代弹出一次,每次函数当前调用自身时都按下.
一个天真的实施@Joel Coehoorn的建议如下:
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)]