use*_*963 7 purely-functional elm
我想用O(1)
复杂度和O(n_max)
预处理来计算第n个Fibonacci数.
要做到这一点,我需要存储以前计算的值,如在此C++代码中:
#include<vector>
using namespace std;
vector<int> cache;
int fibonacci(int n)
{
if(n<=0)
return 0;
if(cache.size()>n-1)
return cache[n-1];
int res;
if(n<=2)
res=1;
else
res=fibonacci(n-1)+fibonacci(n-2);
cache.push_back(res);
return res;
}
Run Code Online (Sandbox Code Playgroud)
但它依赖于榆树不允许的副作用.
Elm中斐波纳契的正常递归定义是:
fib1 n = if n <= 1 then n else fib1 (n-2) + fib1 (n-1)
Run Code Online (Sandbox Code Playgroud)
如果你想要简单的缓存,maxsnew/lazy库应该可以工作.它在本机JavaScript代码中使用一些副作用来缓存计算结果.它通过审查来检查本机代码是否没有向Elm用户公开副作用,为了进行记忆,很容易检查它是否保留了程序的语义.
你应该小心使用这个库.当你创建一个Lazy
值时,第一次强制它需要时间,从那时起它就会被缓存.但是,如果您Lazy
多次重新创建该值,那么它们将不共享缓存.因此,例如,这种DOES NOT工作:
fib2 n = Lazy.lazy (\() ->
if n <= 1
then n
else Lazy.force (fib2 (n-2)) + Lazy.force (fib2 (n-1)))
Run Code Online (Sandbox Code Playgroud)
我通常看到用于斐波纳契的是一个懒惰的列表.我只是给出整个编译代码:
import Lazy exposing (Lazy)
import Debug
-- slow
fib1 n = if n <= 1 then n else fib1 (n-2) + fib1 (n-1)
-- still just as slow
fib2 n = Lazy.lazy <| \() -> if n <= 1 then n else Lazy.force (fib2 (n-2)) + Lazy.force (fib2 (n-1))
type List a = Empty | Node a (Lazy (List a))
cons : a -> Lazy (List a) -> Lazy (List a)
cons first rest =
Lazy.lazy <| \() -> Node first rest
unsafeTail : Lazy (List a) -> Lazy (List a)
unsafeTail ll = case Lazy.force ll of
Empty -> Debug.crash "unsafeTail: empty lazy list"
Node _ t -> t
map2 : (a -> b -> c) -> Lazy (List a) -> Lazy (List b) -> Lazy (List c)
map2 f ll lr = Lazy.map2 (\l r -> case (l,r) of
(Node lh lt, Node rh rt) -> Node (f lh rh) (map2 f lt rt)
) ll lr
-- lazy list you can index into, better speed
fib3 = cons 0 (cons 1 (map2 (+) fib3 (unsafeTail fib3)))
Run Code Online (Sandbox Code Playgroud)
这fib3
是一个包含所有斐波那契数字的惰性列表.因为它在内部使用fib3本身,它将使用相同(缓存)的惰性值,而不需要计算太多.
归档时间: |
|
查看次数: |
507 次 |
最近记录: |