Prolog-实施Eratosthenes筛的麻烦

问题描述

我正尝试在序言中编写一个程序,以查找所有限制为N的质数,我正在尝试使用Sieve of Eratosthenes来实现。我是Prolog的新手,所以我还没有真正掌握递归思考的技巧(您可能会在我的代码中看到它)。

尽管如此,我(或多或少)尝试在序言中实现该算法,但如您在此处看到的那样,并没有走太远:

 allPrimes(N,Primes) :-
     numlist(2,N,Numlist),A is round(sqrt(N)),foreach(between(2,A,_i),sift(_i,Numlist,Primes)).

 sift(_i,Primes) :-
     findall(_j,(member(_j,_j \== _i,(_j mod _i =:= 0)),L),subtract(Numlist,L,Primes).

由于false失败,我一直得到subtract(Numlist,Primes)作为输出,我之所以对它失败的猜测是因为Primes已被实例化,并且其值无法更改。我曾尝试用其他方法解决此问题,但无法提出解决方案。

非常感谢您在正确方向上的指导!

解决方法

实例化后不能更改素数列表。但是,如果未实例化(而不是您的情况),则可以进一步实例化其中的某些项目,并且您可能可以通过这种方式解决此问题。

以下是基于您的算法的递归解决方案:

this.feedSub = this.feedService.getAll().subscribe(results => {
    this.allposts = results.sort((a,b) => a.dateCreated <= b.dateCreated ? 1 : -1);

    this.allposts = this.allposts.filter((post) => {
      return post.category.name.match(ev.detail.value);
    });
});

因此,您构建了可能的整数列表并计算了终止号。然后,您调用采用第一个质数的递归过程allPrimes(N,Primes) :- numlist(2,N,Numlist),Stop is round(sqrt(N)),allPrimes(Numlist,Stop,Primes). allPrimes([N|Numlist],[N|Primes]):- exclude(is_multiple(N),Numlist,MPrimes),(N =< Stop -> allPrimes(MPrimes,Primes) ; Primes=MPrimes). is_multiple(N,I):- I mod N =:= 0. ,然后从列表中排除该数字的所有倍数,并使用其余元素递归调用自身。 完成递归操作后(基本情况是N是停止号),我们重新构建了素数列表。

样品运行:

allPrimes/3