如何在Prolog中找到列表中的正数?

时间:2015-05-31 18:00:15

标签: prolog

我想在prolog中编写一个代码,获取一个列表并找到它的正数并将它们添加到一个新列表中,如下所示:

?- findPositives([-1,2,3,-5,-7,9],Result)
Result : [2,3,9]

我该如何编写此代码?

2 个答案:

答案 0 :(得分:2)

使用tfilter/3

positive_truth(N, true) :-
   N >= 0.
positive_truth(N, false) :-
   N < 0.

?- tfilter(positive_truth, [-1,2,3,-5,-7,9],Result).
Result = [2,3,9]

或者,使用library(clpfd)

pos_truth(Expr, Truth) :-
   Expr #>= 0 #<==> Bool,
   bool01_truth(Bool, Truth).

bool01_truth(0,false).
bool01_truth(1,true).

?- tfilter(pos_truth, [-1,2,3,-5,-7,9],Result).
Result = [2,3,9].

?- tfilter(pos_truth, [X,Y],Result).
   Result = [],     X in inf.. -1, Y in inf.. -1
;  Result = [Y],    X in inf.. -1, Y in 0..sup
;  Result = [X],    X in 0..sup,   Y in inf.. -1
;  Result = [X, Y], X in 0..sup,   Y in 0..sup.

答案 1 :(得分:1)

这将是一个简单的方法:

find_positives( Ns , Ps ) :- findall( X , ( member(X,Ns) , X > 0 ) , Ps ) .

但我怀疑你的导师希望你自己找出一个递归的解决方案。埃尔戈...

find_positives( []     , []     ) .
find_positives( [N|Ns] , [P|Ps] ) :- N >  0 , find_positives(Ns,Ps) .
find_positives( [N|Ns] ,    Ps  ) :- N =< 0 , find_positives(Ns,Ps) .

请注意,您可以通过引入确定性切割来保存比较,因此:

find_positives( []     , []     ) .
find_positives( [N|Ns] , [P|Ps] ) :- N > 0 , ! , find_positives(Ns,Ps) .
find_positives( [_|Ns] ,    Ps  ) :- find_positives(Ns,Ps) .

通过“软切割”/连接(->/2)折叠第2和第3个子句,使其更简洁:

find_positives( []     , [] ) .
find_positives( [N|Ns] , R  ) :-
  ( N > 0 -> R = [P|Ps]; R = Ps ) ,
  find_positives(Ns,Ps) .

是否能提高理解力取决于你。