如何计算序言中的第n个素数
How to count nth prime in prolog
我对 prolog 很陌生,我正在尝试编写一个谓词来给出第 n 个素数的值,它看起来像 nth_prime(N, Prime)
。
我已经完成了计算数字是否为质数的功能
div(X, Y):- 0 is X mod Y.
div(X, Y):- X>Y+1, Y1 is Y+1, div(X, Y1).
prime(2):- true.
prime(X):- X<2, false.
prime(X):- not(div(X, 2)).
我不明白我的下一步是什么,我应该如何计算哪个质数属于 N。
您的代码对于 prolog 来说有点不寻常,但(prime(1)
除外)它可以工作。
这是您的谓词的解决方案:
nextprime(N,N):-
prime(N),
!.
nextprime(P, Prime):-
PP is P+1,
nextprime(PP,Prime).
nthprime(1, 2).
nthprime(N, Prime):-
N>1,
NN is N-1,
nthprime(NN, PrevPrime),
PP is PrevPrime+1,
nextprime(PP, Prime).
?- nthprime(1,P).
P = 2 ;
false.
?- nthprime(2,P).
P = 3 ;
false.
?- nthprime(3,P).
P = 5 ;
false.
其工作原理如下:已知第一个质数为2(nthprime(1, 2).
)。对于每一个大于1
的数N
,得到前一个质数(nthprime(NN, PrevPrime)
),加1直到你碰到一个质数。加 1 部分是通过帮助谓词 nextprime/2
完成的:对于给定的数字 P
,它将检查该数字是否为素数。如果是,它 returns 这个数字,否则它会调用自己为下一个更高的数字 (nextprime(PP,Prime)
) 并转发输出。 bang !
称为剪切,它剪切其他选择分支。因此,如果您一旦命中素数,就无法返回并尝试另一条路径。
要测试它,您可以向 ?- nthprime(N,P).
询问给定的 N
。或者一次检查多个答案,让我们介绍一个 helperpredicate nthprimeList/2
,它为 firstlist 中的每个项目调用 nthprime/2
并将“输出”放入列表中:
nthprimeList([],[]).
nthprimeList([N|TN],[P|TP]):-
nthprime(N,P),
nthprimeList(TN,TP).
?- nthprimeList([1,2,3,4,5,6,7,8,9],[P1,P2,P3,P4,P5,P6,P7,P8,P9]).
P1 = 2,
P2 = 3,
P3 = 5,
P4 = 7,
P5 = 11,
P6 = 13,
P7 = 17,
P8 = 19,
P9 = 23;
false.
根据您的定义,我们定义了以下内容来计算并测试从 2 开始的所有数字,一个接一个:
nth_prime(N, Prime):-
nth_prime(N, Prime, 1, 2). % 2 is the candidate for 1st prime
nth_prime(N, P, I, Q):- % Q is I-th prime candidate
prime(Q)
-> ( I = N, P = Q
; I1 is I+1, Q1 is Q+1, nth_prime(N, P, I1, Q1)
)
; Q1 is Q+1, nth_prime(N, P, I, Q1).
测试:
30 ?- nth_prime(N,P).
N = 1,
P = 2 ;
N = 2,
P = 3 ;
N = 3,
P = 5 ;
N = 4,
P = 7 ;
N = 5,
P = 11 .
31 ?- nth_prime(N,P), N>24.
N = 25,
P = 97 ;
N = 26,
P = 101 ;
N = 27,
P = 103 .
32 ?- nth_prime(N,P), N>99.
N = 100,
P = 541 ;
N = 101,
P = 547 ;
N = 102,
P = 557 .
我对 prolog 很陌生,我正在尝试编写一个谓词来给出第 n 个素数的值,它看起来像 nth_prime(N, Prime)
。
我已经完成了计算数字是否为质数的功能
div(X, Y):- 0 is X mod Y.
div(X, Y):- X>Y+1, Y1 is Y+1, div(X, Y1).
prime(2):- true.
prime(X):- X<2, false.
prime(X):- not(div(X, 2)).
我不明白我的下一步是什么,我应该如何计算哪个质数属于 N。
您的代码对于 prolog 来说有点不寻常,但(prime(1)
除外)它可以工作。
这是您的谓词的解决方案:
nextprime(N,N):-
prime(N),
!.
nextprime(P, Prime):-
PP is P+1,
nextprime(PP,Prime).
nthprime(1, 2).
nthprime(N, Prime):-
N>1,
NN is N-1,
nthprime(NN, PrevPrime),
PP is PrevPrime+1,
nextprime(PP, Prime).
?- nthprime(1,P).
P = 2 ;
false.
?- nthprime(2,P).
P = 3 ;
false.
?- nthprime(3,P).
P = 5 ;
false.
其工作原理如下:已知第一个质数为2(nthprime(1, 2).
)。对于每一个大于1
的数N
,得到前一个质数(nthprime(NN, PrevPrime)
),加1直到你碰到一个质数。加 1 部分是通过帮助谓词 nextprime/2
完成的:对于给定的数字 P
,它将检查该数字是否为素数。如果是,它 returns 这个数字,否则它会调用自己为下一个更高的数字 (nextprime(PP,Prime)
) 并转发输出。 bang !
称为剪切,它剪切其他选择分支。因此,如果您一旦命中素数,就无法返回并尝试另一条路径。
要测试它,您可以向 ?- nthprime(N,P).
询问给定的 N
。或者一次检查多个答案,让我们介绍一个 helperpredicate nthprimeList/2
,它为 firstlist 中的每个项目调用 nthprime/2
并将“输出”放入列表中:
nthprimeList([],[]).
nthprimeList([N|TN],[P|TP]):-
nthprime(N,P),
nthprimeList(TN,TP).
?- nthprimeList([1,2,3,4,5,6,7,8,9],[P1,P2,P3,P4,P5,P6,P7,P8,P9]).
P1 = 2,
P2 = 3,
P3 = 5,
P4 = 7,
P5 = 11,
P6 = 13,
P7 = 17,
P8 = 19,
P9 = 23;
false.
根据您的定义,我们定义了以下内容来计算并测试从 2 开始的所有数字,一个接一个:
nth_prime(N, Prime):-
nth_prime(N, Prime, 1, 2). % 2 is the candidate for 1st prime
nth_prime(N, P, I, Q):- % Q is I-th prime candidate
prime(Q)
-> ( I = N, P = Q
; I1 is I+1, Q1 is Q+1, nth_prime(N, P, I1, Q1)
)
; Q1 is Q+1, nth_prime(N, P, I, Q1).
测试:
30 ?- nth_prime(N,P).
N = 1,
P = 2 ;
N = 2,
P = 3 ;
N = 3,
P = 5 ;
N = 4,
P = 7 ;
N = 5,
P = 11 .
31 ?- nth_prime(N,P), N>24.
N = 25,
P = 97 ;
N = 26,
P = 101 ;
N = 27,
P = 103 .
32 ?- nth_prime(N,P), N>99.
N = 100,
P = 541 ;
N = 101,
P = 547 ;
N = 102,
P = 557 .