0

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).

N=01行目では、 のときに再帰を停止するように基本ケースを作成するにはどうすればよいですか? これは正しいです?

次の 2 つの節については、論理プログラミングの観点から考えるのに苦労しています。これは間違いなくロジックプログラミングスタイルではないと感じています。

失敗した場合はisPrime(X)何も保存せずに次の番号に進みますが、isPrime(X)が真の場合は再帰して次の番号に進み、 を保存しXます。

Prologでそれを行うにはどうすればよいですか?

4

2 に答える 2

3

まず第一に、2 つだけが必要な場合は、メインの述語に 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).
于 2012-09-16T11:45:33.277 に答える
2

これがあなたが書くつもりだったものです:

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
于 2012-09-17T05:55:06.873 に答える