2015-04-21 3 views
1

У меня есть задача с бесконечными списками.ERLANG, бесконечный список Фибоначчи с использованием zipWith

Я должен написать zipWith/3 для бесконечных списков - сделано

Я должен использовать этот zipWith/3, чтобы создать бесконечный список чисел Фибоначчи с Фибо/0 - проблема

я должен написать выдумки (N), принимая первые 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()). 

Я знаю приврать/1 должен выглядеть следующим образом (я довольно сюр е-исправьте меня, если я ошибаюсь). Принимая сам список и список без головы. Поэтому в случае [0,1, ...] zipWith (add, [0,1, ...], [1, ...]) приводит к добавлению последних двух чисел. Но все, что я пытаюсь как начало этого fib() -> ..., приводит к ошибкам. Я хочу выразить это примерно так: fib() -> fib ([[0,1] ++ fun() -> ... end] ...)

Я как-то хотел начать фид/1 с [0,1, fun() ...], но не узнайте, как запустить список.

Заранее спасибо за советы

ответ

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

Идея состоит в том, чтобы построить некоторый элемент, а затем передать контекст для следующего номера.

На самом деле я не думаю, что этот подход реализует истинную лень, поскольку вам нужно переоценивать все значения каждый раз, когда вы просматриваете список.

UPDATE

Если вы хотите ралли осуществить это через zipWith, вы можете играть на том, что каждый следующий элемент последовательности формируется как сумма предыдущего и текущего.

Таким образом, вы можете взять список элементов и список элементов, сдвинутых на один, и сформировать каждый следующий элемент в виде суммы элемет в этих списках.

Вам понадобится несколько первых элеметров для бутстрапа. Вы просто применить знания из первых двух элементов

enter image description here

Как вы можете видеть, время расчета 3-го элемента, вы должны знать 2 первых, при расчете 4-го элемента, вы должны знать 2rd и третий, но вы уже рассчитали третий.

%% 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. Более интересная задача такого рода - реализовать Сито Эратосфена.Последняя задача не так искусна, и ленивая душа такого рода действительно изящна для него
+0

Проблема в том, что задача говорит использовать zipWith. Я попробую и посмотрю, что ваш подход может мне помочь. Благодарю. – user3556115

+0

Чем вы очень. – user3556115

+0

Не могли бы вы объяснить, когда случай e (L) is_list и когда is_function произойдет и почему мы должны сделать это различие? Я этого не понимаю. Я думал, что это должно работать без e(), потому что всегда есть список Lazy, который всегда забавный, но в некоторых случаях он должен быть другим. Где? – user3556115

Смежные вопросы