1

I want to write a code in prolog that gets a list and find its positive numbers and adds them into a new list as below :

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

How can I write this code?

false
  • 10,264
  • 13
  • 101
  • 209
Amir Jalilifard
  • 2,027
  • 5
  • 26
  • 38

2 Answers2

2

Using 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].

Alternatively, using 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.
false
  • 10,264
  • 13
  • 101
  • 209
1

this would be the simple way:

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

But I suspect that your instructor would like you to figure out a recursive solution on your own. Ergo...

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

Note that you could save a comparison by introducing a deterministic cut, thus:

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

And make it a little more succinct by collapsing the 2nd and 3rd clauses by a 'soft cut'/conjunction (->/2):

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

Whether that improves comprehension or not is left up to you.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • 1
    Your first and 2nd answer lacks a `N = P`. Your 2nd succeeds for `find_positives([1],[])` but should rather fail. – false Jun 01 '15 at 20:53