How to remove even numbers in List using Prolog

前端 未结 5 1518
隐瞒了意图╮
隐瞒了意图╮ 2021-01-14 16:52

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],         


        
5条回答
  •  南方客
    南方客 (楼主)
    2021-01-14 17:33

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

    Edit 2015-06-06

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

提交回复
热议问题