I need to remove all even numbers in first list and save the rest to second list. My first non-working approach was:
remove_even([],[]).
remove_even([H1|T1],
If your Prolog system offers clpfd, then this answer is for you. (If not, please read on, too!)
By using meta-predicate tfilter/3 and the reified predicate zodd_t/2, simply write:
?- tfilter(zodd_t,[1,2,3,4],Zs). % remove even integers = keep odd integers Zs = [1,3].
As we only use monotone code here, we get sound answers for more general queries, too:
?- tfilter(zodd_t,[A,B,C],Zs). Zs = [ ], A mod 2 #= 0, B mod 2 #= 0, C mod 2 #= 0 ; Zs = [ C], A mod 2 #= 0, B mod 2 #= 0, C mod 2 #= 1 ; Zs = [ B ], A mod 2 #= 0, B mod 2 #= 1, C mod 2 #= 0 ; Zs = [ B,C], A mod 2 #= 0, B mod 2 #= 1, C mod 2 #= 1 ; Zs = [A ], A mod 2 #= 1, B mod 2 #= 0, C mod 2 #= 0 ; Zs = [A, C], A mod 2 #= 1, B mod 2 #= 0, C mod 2 #= 1 ; Zs = [A,B ], A mod 2 #= 1, B mod 2 #= 1, C mod 2 #= 0 ; Zs = [A,B,C], A mod 2 #= 1, B mod 2 #= 1, C mod 2 #= 1.
We can use above code even without clpfd, simply by using different reified predicates: eveninteger_t/2 → zeven_t/2, and oddinteger_t/2 → zodd_t/2.
Sample query:
?- tfilter(oddinteger_t,[1,2,3,4,5,6,7],Xs). Xs = [1,3,5,7].
Let's try the following variation!
Instead of using zodd_t/2
directly, rather use zeven_t/2
and not_t/3
:
truth_negated(true,false).
truth_negated(false,true).
not_t(Goal,Param,Truth1) :- % meta-predicate, negate truth value
call(Goal,Param,Truth0),
truth_negated(Truth0,Truth1).
Let's see it if works with a head-to-head comparison:
?- tfilter( zodd_t ,[1,2,3,4],Zs). Zs = [1,3]. ?- tfilter(not_t(zeven_t),[1,2,3,4],Zs). Zs = [1,3].