在列表Prolog中find2的幂

我试图在Prolog(SWI Prolog)中创build一个列表,并检查哪些数字是2的幂,然后查找列表中具体数字的次数(在这个例子中,我试图找出数字的次数3在列表中)。 举个例子,如果你问

?- check([0,2,3,-5,-2,1,8,7,4], MULT2, THREE). 

你应该看看

 MULT2=[2,8,4] THREE=1 

我的第一个尝试find一个解决scheme是search头部和头部mod 2 = 0find所有的数字是2的权力,但出了问题,我只得到“假”作为答案。

以下是如何以逻辑纯粹的方式find“两个幂”的方法!

将元谓词tfilter/3power_of_two_t/2结合使用:

 power_of_two_t(Expr,T) :- ( I is Expr, I > 0, 0 is I /\ (I-1) -> T = true ; T = false ). 

示例查询:

 ?- tfilter(power_of_two_t, [0,2,3,-5,-2,1,8,7,4], Ps). Ps = [2,1,8,4] % succeeds, but leaves choicepoint ; false. 

tfilter/3使用第一个参数索引,我们可以做得更好

 tfilter(Pred_2,Xs,Zs) :- list_tfilter_list(Xs,Pred_2,Zs). list_tfilter_list([], _CT_2,[]). list_tfilter_list([E|Es],CT_2,Fs0) :- if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs ), list_tfilter_list(Es,CT_2,Fs). 

让我们看看它的行动:

 ?- tfilter(power_of_two_t, [0,2,3,-5,-2,1,8,7,4], Ps). Ps = [2,1,8,4]. % succeeds deterministically 

在一个谓词中做两个不同的任务是一件奇怪的事情。 你应该有两个单独的谓词,一个用于计算2的幂数,一个用于计数3s。 那么你可以把它们合并成一个谓词:

 check(Nums, MULT2, THREE) :- count2powers(Nums, MULT2), count3s(Nums, THREE). 

之后,你可以进一步分解,并有一个单独的谓词来检查一个数是否是2的幂:

 is2power(1). is2power(N) :- N > 0, N2 is N // 2, N2 * 2 =:= N, is2power(N2). 

这是基本的软件工程,这样你可以逐步build立你的程序,你将能够提出更具体和有意义的问题,而不仅仅是“整个程序返回假”。