我对Prolog的递归功能有疑问。我相信我没有正确实施并需要帮助。
我需要生成前N个素数并将其返回列表中。生成素数不是问题,而是在列表中生成它是我的问题。
这是相关代码的一部分:
genList(_, 0, _).
genList(X, N, PrimeList, PrimeList):-
N > 0,
isprime(X),
X1 is X +1,
N1 is N -1,
genList(X1,N1,[X|PrimeList], [X|PrimeList]),!.
genList(X, N, PrimeList, PrimeList):-
N>0,
\+isprime(X),
X1 is X + 1,
genList(X1,N,PrimeList, PrimeList).
这是我在Prolog解释器中输入的内容:
genList(1,N, [],L).
对于第1行,如何制作基本案例,以便在N=0
时,我停止递归?这是对的吗?
至于接下来的两个条款,我在思考逻辑编程时遇到了困难。我当然觉得这不是逻辑编程风格。
我想说当isPrime(X)
失败时,我们会继续使用下一个数字而不保存任何内容,但当isPrime(X)
为真时,我们会递归并继续下一个数字,保存{{1 }}
我如何在Prolog中做到这一点?
答案 0 :(得分:4)
首先,如果你只想要两个参数,你的主谓词不需要4个参数。在这里,您需要第一个素数列表N
。因此,N
的参数和列表的参数应该足够了:
primeList(N, L) :-
% eventually in the body a call to a worker predicate with more arguments
现在,您的逻辑用这些术语解释:
primeList(N, [N|L]) :-
% If we're not at the base case yet
N > 0,
% If N is a prime
isPrime(N),
NewN is N - 1,
% Let's recurse and unifie N as the head of our result list in the head
% of the predicate
primeList(NewN, L).
primeList(N, L) :-
% Same as above but no further unification in the head this time.
N > 0,
% Because N isn't a prime
\+ isPrime(N),
NewN is N - 1,
primeList(NewN, L).
为此,您必须添加基本案例
primeList(0, []).
您可以使用以下内容重写该内容:
primeList(0, []) :- !.
primeList(N, [N|L]) :-
isPrime(N),
!,
NewN is N - 1,
primeList(NewN, L).
primeList(N, L) :-
NewN is N - 1,
primeList(NewN, L).
答案 1 :(得分:3)
这是你打算写的:
genList(N, L) :- genList(2, N, L, []).
genList(X, N, L, Z):- % L-Z is the result: primes list of length N
N > 0 ->
( isprime(X) -> L=[X|T], N1 is N-1 ; L=T, N1 is N ),
X1 is X + 1,
genList(X1,N1,T,Z)
;
L = Z.
if-then-else 构造体现了削减。你是对的,它本质上是一种功能编程风格。
我们可以对它进行一些修改,不允许0个素数的请求(无论如何都没有意义),这样我们也可以回到最后生成的素数:
genList(1, [2], 2) :- !.
genList(N, [2|L], PN) :- N>1, L=[3|_], N2 is N-2, gen_list(N2, L, [PN]).
gen_list(N, L, Z) :- L=[P|_], X is P+2, gen_list(X, N, L, Z).
gen_list(X, N, L, Z) :- % get N more odd primes into L's tail
N > 0 ->
( isprime(X) -> L=[_|T], T=[X|_], N1 is N-1 ; L=T, N1 is N ),
X1 is X + 2,
gen_list(X1,N1,T,Z)
;
L = Z. % primes list's last node
运行它:
?- genList(8,L,P).
L = [2, 3, 5, 7, 11, 13, 17, 19]
P = 19
这也使我们能够从停止的那一刻起停止并继续素数生成,而不是从头开始:
?- L = [3|_], gen_list(8, L, Z), Z=[P10|_], writeln([2|L]),
gen_list(10, Z, Z2), Z2=[P20], writeln(Z).
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29|_G1037]
[29,31,37,41,43,47,53,59,61,67,71]
P10 = 29
P20 = 71