在尝试学习Prolog时,我遇到了一个很好的练习,那就是编写一个显示Nth Fibonacci数的程序。经过一些工作后,我开始工作,然后决定是否可以编写一个程序,根据输入显示一系列Fibonacci数字。
例如输入:
?- fib_sequence(2,5,Output).
给出输出:
?- Output = [1,1,2,3]
然而,我很难找到一个好的起点。这就是我到目前为止所做的:
fib(0, 0).
fib(1, 1).
fib(N, F) :- X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
fib_sequence(A,B,R) :- fib(A,Y) , fib(B,Z).
我知道我必须为 R 分配一个值,但我不确定如何分配多个值。非常感谢任何帮助。
答案 0 :(得分:3)
观察您的fib_sequence
无法在单个谓词子句中完成:您需要至少两个来保持递归 - 一个在A
大于B
时生成一个空列表(即我们已经耗尽了从A到B的范围),另一个将X
从fib(A,X)
添加到您正在构建的列表中,通过A
增加1
,并递归调用fib_sequence
以生成序列的其余部分。
第一个谓词子句如下所示:
fib_sequence(A,B,[]) :- A > B.
第二个谓词条款有点难:
fib_sequence(A,B,[H|T]) :-
A =< B /* Make sure A is less than or equal to B */
, fib(A, H) /* Produce the head value from fib(A,...) */
, AA is A + 1 /* Produce A+1 */
, fib_sequence(AA, B, T). /* Produce the rest of the list */
答案 1 :(得分:1)
Prolog有一些内置的帮助器来处理数字序列,然后作为dasblinkenlight回答的替代方法,这里是一个惯用的'查询':
fib_sequence(First, Last, Seq) :-
findall(F, (between(First,Last,N), fib(N,F)), Seq).
请注意,它不会与你的fib / 2开箱即用,因为有一个错误:我添加了一个条件,避免你尝试回溯的无限循环 on fib / 2解决方案:
fib(N, F) :- N > 1, % added sanity check
X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
答案 2 :(得分:1)
这是另一种方法。首先,我稍微重新设置fib
,以便它只递归调用一次而不是两次。为此,我创建了一个谓词,它返回前两个Fibonacci值而不是最后一个:
fib(N, F) :-
fib(N, F, _).
fib(N, F, F1) :-
N > 2,
N1 is N-1,
fib(N1, F1, F0),
F is F0 + F1.
fib(1, 1, 0).
fib(2, 1, 1).
为了获得序列,我选择了一个内置Fibonacci计算的算法,这样就不需要调用fib
O(n ^ 2)次。但是,它确实需要在完成后反转列表:
fib_sequence(A, B, FS) :-
fib_seq_(A, B, FSR),
reverse(FSR, FS).
fib_sequence_(A, B, []) :-
A > B.
fib_sequence_(A, B, [F]) :-
A =:= B,
fib(A, F, _).
fib_sequence_(A, B, [F1,F0]) :-
1 is B - A,
fib(B, F1, F0).
fib_sequence_(A, B, [F2,F1,F0|FT] ) :-
B > A,
B1 is B - 1,
fib_sequence_(A, B1, [F1,F0|FT]),
F2 is F1 + F0.
这是另一种方法,没有相反的方法,但上面的反向方法似乎仍然执行得快一点。
fib_sequence_dl(A, B, F) :-
fib_sequence_dl_(A, B, F, [_,_|[]]).
fib_sequence_dl_(A, B, [], _) :-
A > B, !.
fib_sequence_dl_(A, B, [F], _) :-
A =:= B,
fib(A, F, _), !.
fib_sequence_dl_(A, B, [F0,F1|T], [F0,F1|T]) :-
1 is B - A,
fib(B, F1, F0), !.
fib_sequence_dl_(A, B, F, [F1,F2|T]) :-
A < B,
B1 is B - 1,
fib_sequence_dl_(A, B1, F, [F0,F1|[F2|T]]),
F2 is F0 + F1.