如何迭代一些“记忆”机制?

时间:2016-11-01 02:41:54

标签: python recursion memory queue

给定一个函数f(x),目标是递归调用f(x),但输出的内存为2步。即:

>>> def f(x): return x**2
... 
>>> memory = original = 3
>>> x0 = f(original)
>>> x1 = f(x0+memory)
>>> memory = x0
>>> x2 = f(x1+memory)
>>> memory = x1
>>> x3 = f(x2+memory)
>>> memory = x2
>>> x4 = f(x3+memory)
>>> x4
307766666167459524

我可以保存一个列表,然后在递归中存储每次迭代的所有输出:

>>> original = 3
>>> memory = []
>>> memory.append(original)
>>> memory.append(f(original))
>>> for i in range(4):
...     memory.append(f(memory[-1]+memory[-2]))
... 
>>> memory[-1]
307766666167459524

但是想象一下,保存这些输出是一项昂贵的任务,因为我使用的实际f(x)存储了一些巨大数量的浮点,并且它不仅仅是一个正方形。

我还可以将最后2个内存插槽存储为花哨的deque

>>> from collections import deque
>>> original = 3
>>> q = deque([original, f(original)])
>>> for i in range(4):
...     q.append(f(q[-1]+q.popleft()))
... 
>>> q[-1]
307766666167459524

我还能用某种形式的记忆机制来执行这种递归功能吗?

想象一下,如果内存更复杂,我需要存储的不只是-2而是-n而且我必须访问[-n:-1]元素?您的解决方案是否适应这种情况?

3 个答案:

答案 0 :(得分:1)

当您必须处理无限序列时,Python生成器是一个很好的解决方案。

在您的示例中,如果您只需要访问最后两个元素,则可以使用以下生成器函数:

def f_generator(x):
    l = [x, f(x)]
    while True:
        res = f(l[0]+l[1])
        l.pop(0)
        l.append(res)
        yield res

outputs = f_generator(3)
for i in range(4):
    print(outputs.next())

如果您需要在生成器函数中访问两个以上的元素,则需要通过将要访问的元素数量作为参数传递,并修改列表初始化(l = [x, f(x)])和计算下一个元素(res = f(l[0]+l[1]))。

答案 1 :(得分:0)

这应该适合您的问题:

mem = [3,9]

表示范围(2,x)中的i:

mem.append(f(mem[-1] + mem[-2]))
# if mem have more than n elements, pop the first one
if len(mem) > n:
    mem.pop(0)

现在,如果x足够大,mem将存储n个值并且f(x-i)= mem [-i]

答案 2 :(得分:0)

生成器听起来就像你之后的那样,因为它会懒洋洋地生成序列中的下一个元素。如果你使它足够通用,你可以稍后重复使用:

  • 不同的功能
  • 不同的种子,
  • 不同的内存长度

例如:

def do_on_last_n_generator(f, n, seed):
internal_list = [seed]
while True:
    internal_list.append(f(internal_list, n))
    if len(internal_list)>n:
        internal_list.pop(0)
    yield internal_list[-1]

然后你可以提供一个功能,例如

def my_sum_func(a_list, n): # sum the last n elements
    return sum(a_list[-n:])

然后让自己成为一名发电机。在这里你可以决定种子数(我用1)和记忆元素(这里我用4):

sum_last_four = do_on_last_n_generator(my_sum_func, 4, 1)

然后每次你想获得下一个元素:

next_number = next(sum_last_four)

或者你可以让它们循环:

for i in range(10):
    print(next(sum_last_four)

如果您稍后决定实际上想要对最后十个元素求和,那么只需创建一个新的生成器:

sum_last_ten = do_on_last_n_generator(my_sum_func, 10, 1)

您可以类似地更改功能和种子。