Prolog找到N个素数

时间:2012-09-16 11:15:40

标签: prolog primes

我对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中做到这一点?

2 个答案:

答案 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