我已经查看了无数其他类似的问题,但我还没有找到可行的解决方案,所以我问这个:
我有一个规则:
check_prime(X) :-
X > 0,
X0 is X - 1,
(X =:= 1 -> true; X =:= 2 -> true; foreach(between(2, X0, T), X mod T =\= 0) -> true; false).
然后我想跑步:
B is [0],
foreach(between(1, 50, T), (check_prime(T) -> B2 = [B, T], write(B2); !)).
这成功地将 [0, primeNumber] 对写入控制台。我也可以这样做:
B is [0], foreach(between(1, 50, T), (check_prime(T) -> (write(T), write(", ")); !)).
实际上以一种漂亮的方式打印了所有内容,减去了列表的缺失以及末尾的额外逗号。
这个写入函数正在递归地处理 check_prime(T) 的解决方案,一次一个解决方案。我想列出所有这些解决方案,但无论我尝试什么,我要么无法获得对象持久性(写入的原子类似于_31415926),要么遇到各种错误。
由于每个素数都是递归找到的,因此如何动态创建素数列表?
编辑:
我尝试过改变“if true”分支,但它仍然存在问题:
如何动态创建素数列表?
使 check_prime 检查一个数字是否是素数(而不是其他):
check_prime(1).
check_prime(2).
check_prime(X1) :-
X1 > 2,
succ(X0, X1),
forall(between(2, X0, N), \+ (0 is X1 mod N)).
然后用它来制作素数列表,例如:
?- findall(X, (between(1, 50, X), check_prime(X)), Primes).
Primes = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
或
primes_to(X, Primes) :-
numlist(1, X, Nums),
include(check_prime, Nums, Primes).
?- primes_to(50, Primes).
Primes = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
如果您确实想要递归地而不是方便地执行此操作,则构建器会在计数器为 0 时将某些内容添加到素数列表中,而如果计数器不是 0 则不会:
primes_to(0, []).
primes_to(Counter, [Counter|Primes]) :-
check_prime(Counter),
Counter0 is Counter - 1,
primes_to(Counter0, Primes).
primes_to(Counter, Primes) :-
\+ check_prime(Counter),
Counter0 is Counter - 1,
primes_to(Counter0, Primes).
?- primes_to(50, Primes).
Primes = [47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2, 1]