ERLANG,使用zipWith的无限斐波纳契列表

时间:2015-04-21 08:11:29

标签: list erlang fibonacci infinite

我有一个无限列表的任务。

我必须为无限列表编写一个zipWith / 3 - 已完成

我必须使用这个zipWith / 3来创建一个无限的fibonacci数字列表,其中包含fib / 0 - 问题

我必须从fib() - 完成

中获取前N个元素的fibs(N)

这是我到目前为止所做的:

-module(zipWith).
-export([take/2, zipWith/3, fib/0]).

take(0, _)         -> [];
take(N, [H|LazyT]) -> [H | take(N-1, LazyT())].

zipWith(F, [H1|L1], [H2|L2]) -> [F(H1, H2) | fun() -> zipWith(F, L1(),   L2()) end].

fib() -> ...
fib(L) -> zipWith(fun(X,Y) -> X + Y end, L(), tl(L())).

fibs(N) -> take(N, fib()).

我知道fib / 1应该是这样的(我很确定 - 如果我弄错了,请纠正我)。列表本身和列表没有头。因此,如果[0,1,...] zipWith(add,[0,1,...],[1,...])导致添加最后两个数字。但无论我尝试作为这个fib()的开始 - > ...导致错误。 我想以某种方式表达它: fib() - > fib([[0,1] ++ fun() - > ... end] ...)

我不知何故想用[0,1,fun()...]启动fib / 1,但是不知道如何让列表开始。

提前感谢您的建议

1 个答案:

答案 0 :(得分:2)

我不明白你将如何在这里使用zipwith。但是,我提出了以下解决方案:

map(_, []) -> [];
map(F, [H | T]) -> [F(H) | fun() -> map(F, T()) end].

fib1(X, Y) -> [{X, Y} | fun() -> fib1(Y, X+Y) end].

fib() -> map(fun({_X, Y}) -> Y end, fib1(1,1)).

想法是构建一些元素,然后传递下一个数字的上下文。

实际上,我并不认为这种方法可以实现真正的懒惰,因为每次进入列表时都必须重新评估所有值。

更新

如果你想通过zipWith实现这一点,你可以解决这个问题,即序列的每个下一个元素都是前一个元素和当前元素的总和。

因此,您可以获取元素列表,以及一个元素列表,并将每个下一个元素组合为这些列表中elemet的总和。

你需要一些先进的elemetns来引导。您只需应用前两个元素的知识

enter image description here

正如你所看到的,在计算第3个元素的时候你必须首先知道2,在计算第4个元素时,你必须知道第2个和第3个,但你已经计算了第3个。

%% this eveluates the lazy list and just returns normal one
e(L) when is_list(L) -> L; 
e(LazyL) when is_function(LazyL, 0) -> LazyL().

take(0, _)         -> [];
take(N, [H|LazyT]) -> [H | take(N-1, e(LazyT))].

drop(0, T)         -> e(T);
drop(N, [_|LazyT]) -> drop(N-1, e(LazyT)).

zipWith(F, [H1|L1], [H2|L2]) -> [F(H1, H2) | fun() -> zipWith(F, e(L1),   e(L2)) end].

fib() -> [1, 1 | fun() -> zipWith(fun(X,Y) -> X + Y end, fib(), drop(1, fib())) end ].

fibs(N) -> take(N, fib()).

最后的注释

  1. 永远不要在现实生活中这样写。
  2. 这种更有趣的任务是实施Eratosthenes筛选。后一个任务不是那么人为,而且这种懒惰的灵魂对它来说真的很优雅
相关问题