在列表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/3
与power_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立你的程序,你将能够提出更具体和有意义的问题,而不仅仅是“整个程序返回假”。