在Prolog列表中查找2的幂

时间:2014-02-03 01:38:12

标签: list prolog clpfd clpz

我正在尝试在Prolog(SWI Prolog)中创建一个列表,并检查哪些数字是2的幂,然后查找列表中特定数字的次数(在此示例中,我试图找到多少次)次数3在列表中)。 例如,如果你问

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

你应该看到

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

我第一次尝试找到一个解决方案是用头部搜索列表并且做头部mod 2 = 0来找到所有2的幂数,但是出了点问题我只得到“假”作为答案。

2 个答案:

答案 0 :(得分:5)

以下是你如何以逻辑上纯粹的方式找到“两个人的力量”!

使用 4.3.5,library(reif)library(clpz)

:- use_module([library(reif), library(clpz)]).

power_of_two_t(I, T) :-
   L #= min(I,1),
   M #= I /\ (I-1),
   call((L = 1, M = 0), T).      % using (=)/3 and (',')/3 of library(reif)

使用元谓词tfilter/3power_of_two_t/2结合使用的示例查询 1

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

以下是评论建议的更一般的查询:

?- tfilter(power_of_two_t, [X], Ps).
   Ps = [X], 0#=X/\_A, _A+1#=X, X in 1..sup, _A in 0..sup
;  Ps = [], dif(_A,0), _A#=X/\_B, _B+1#=X, X in 1..sup, _B in 0..sup
;  Ps = [], dif(_A,1), _A#=min(X,1), _B#=X/\_C, _C+1#=X, X#>=_A, _A in inf..1.

脚注1:上面显示的答案序列被刷新以表明呼叫的确定性。 功能

脚注2:要重现结果,请使用call_det/2,其定义如下:

call_det(G_0, Det) :-
   call_cleanup(G_0, Flag = set),
   (  nonvar(Flag)
   -> Det = true
   ;  Det = false
   ).

答案 1 :(得分:1)

在一个谓词中执行两个这样的不同任务是一件奇怪的事情。你可能应该有两个单独的谓词,一个用于计算2的幂数,一个用于计算3个。然后你可以将它们组合在一个谓词中,如:

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).

这是基本的软件工程,通过这种方式,您可以逐步构建程序,并且您可以提出更具体和有意义的问题,而不仅仅是“整个程序返回错误。”