簡體   English   中英

如何在prolog列表中存儲遞歸函數的值?

[英]How to store the value of a recursive function in a list in prolog?

我的任務是:

給定函數f的以下定義,創建一個Prolog程序來計算所有0 <i <32的f(i)。

  • f(0)= 0
  • f(1)= 1
  • 對於n> 1,f(n)= f(n-2)+ 2 * f(n-1)

到目前為止我的代碼是:

problemThree(0, 0).
problemThree(1, 1).
problemThree(N, NF) :-
    N > 1,
    A is N - 2,
    B is N - 1,
    problemThree(A, AF),
    problemThree(B, BF),
    NF is AF + 2*BF.

它正在發揮作用,但它將永遠顯示N> 20的值。

請告訴我如何將值存儲在列表中以使程序更快。

這是一個DCG方法,它將序列生成為列表:

prob3(1, F0, F1) --> [F0, F1].
prob3(N, F0, F1) --> {N > 1, F2 is 2*F1 + F0, N1 is N-1}, [F0], prob3(N1, F1, F2).

prob3(0, [0]).
prob3(N, FS) :-
    phrase(prob3(N, 0, 1), FS).

?- prob3(10, L).
L = [0, 1, 2, 5, 12, 29, 70, 169, 408, 985] ;
false.

?- prob3(169, L).
L = [1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025,
..., 17280083176824678419775054525017769508908307965108250063833395641] ;
false

?- time((prob3(1000, L),false)).
% 3,011 inferences, 0.005 CPU in 0.005 seconds (100% CPU, 628956 Lips)
false.


請注意,對於長列表答案,SWI Prolog將縮寫輸出,例如:

?- prob3(20, L).
L = [0, 1, 2, 5, 12, 29, 70, 169, 408|...] [write]   % PRESSED 'w' here
L = [0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025, 470832, 1136689, 2744210, 6625109, 15994428] ;
false

?-

這只是SWI Prolog通過大量輸出不會弄亂屏幕的方式。 在這里,你可以用w回答,它將給出整個結果:

 ?- prob3(20, L). L = [0, 1, 2, 5, 12, 29, 70, 169, 408|...] [write] % PRESSED 'w' here L = [0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 33461, 80782, 195025, 470832, 1136689, 2744210, 6625109, 15994428] ; false ?- 

請參閱, 幫助:我想要整個答案

無需存儲超過前兩個數字!

這是我從臀部快速而骯臟的鏡頭:

p3(N,F) :- 
   (  N =:= 0 -> F = 0
   ;  N =:= 1 -> F = 1
   ;  N  >  1 -> N0 is N-2, p3_(N0,0,1,F)
   ).

p3_(N,F0,F1,F) :- 
   F2 is F0 + 2*F1,
   (  N =:= 0
   -> F2 = F
   ;  N0 is N-1,
      p3_(N0,F1,F2,F)
   ).

示例查詢:

?- between(25,35,N), p3(N,F).
  N = 25, F = 1311738121
; N = 26, F = 3166815962
; N = 27, F = 7645370045
; N = 28, F = 18457556052
; N = 29, F = 44560482149
; N = 30, F = 107578520350
; N = 31, F = 259717522849
; N = 32, F = 627013566048
; N = 33, F = 1513744654945
; N = 34, F = 3654502875938
; N = 35, F = 8822750406821.

更大的東西一點點

?- p3(111,F).
F = 1087817594842494380941469835430214208491185.

?- p3(123,F).
F = 42644625325266431622582204734101084193553730205.

?- p3(169,F).
F = 17280083176824678419775054525017769508908307965108250063833395641.

夠快嗎?

?- time((between(0,1000,N), p3(N,_), false)).
% 2,006,005 inferences, 0.265 CPU in 0.265 seconds (100% CPU, 7570157 Lips)
false.

雖然它比其他答案慢得多,但我喜歡這個具有功能精神的人:

:- use_module(library(lambda)).

f(N, FN) :-
    cont_f(N, _, FN, \_^Y^_^U^(U = Y)).

cont_f(N, FN1, FN, Pred) :-
    (   N < 2 ->
        call(Pred, 0, 1, FN1, FN)
    ;
        N1 is N - 1,
        P = \X^Y^Y^U^(U is X + 2*Y),
        cont_f(N1, FNA, FNB, P),
        call(Pred, FNA, FNB, FN1, FN)
    ).

記憶是有用的,我把它用於使用Erathostenes篩的加速計算

?- time((between(0,1000,N), prob3(N,_), false)).
% 10,939 inferences, 0.011 CPU in 0.012 seconds (99% CPU, 951780 Lips)

:- dynamic memo/2.
prob3(0, 0).
prob3(1, 1).
prob3(N, R) :- memo(N, R), !.
prob3(N, R) :-
    N > 1, N2 is N-2, N1 is N-1, prob3(N2,R2), prob3(N1,R1), R is R2+2*R1, assertz(memo(N, R)).

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM