different/2 - does a pure, determinate definition exist?

后端 未结 8 1023
野的像风
野的像风 2020-12-07 00:24
different(Xs, Ys) :-
   member(X, Xs),
   non_member(X, Ys).
different(Xs, Ys) :-
   member(Y, Ys),
   non_member(Y, Xs).

While this definition usi

8条回答
  •  北海茫月
    2020-12-07 00:52

    Next contestant to the code beauty pageant!-)

    This answer shows a refactored variation of code shown in a previous answer. It uses reified conjunction and disjunction:

    and_(P_1,Q_1) :-
       and_t(P_1,Q_1,true).
    
    or_(P_1,Q_1) :-
       or_t(P_1,Q_1,true).
    
    and_t(P_1,Q_1,Truth) :-
       if_(P_1, call(Q_1,Truth), Truth=false).
    
    or_t(P_1,Q_1,Truth) :-
       if_(P_1, Truth=true, call(Q_1,Truth)).
    

    Note the two versions for both "and" and "or"; the ones with suffix _t have an extra argument for the truth value, the ones without the suffix do not and assume that Truth=true should hold.

    Based on and_t/3 and on reified term inequality predicate dif/3, we define nonmember_t/3:

    nonmember_t(X,Ys,Truth) :-
       list_nonmember_t(Ys,X,Truth).
    
    list_nonmember_t([]    ,_, true).
    list_nonmember_t([Y|Ys],X,Truth) :-
       and_t(dif(X,Y), list_nonmember_t(Ys,X), Truth).
    

    Now, let's define some_absent_t/3, different_t/3 and different/2, like so:

    some_absent_t([]    ,_ ,false).
    some_absent_t([X|Xs],Ys,Truth) :-
       or_t(nonmember_t(X,Ys), some_absent_t(Xs,Ys), Truth).
    
    different_t(Xs,Ys,Truth) :-
       or_t(some_absent_t(Xs,Ys),
            some_absent_t(Ys,Xs),
            Truth).
    
    different(Xs,Ys) :-
       different_t(Xs,Ys,true).
    

    Does it still run?

    ?- different([A,B],[X,Y]).
          A=X ,               B=X ,           dif(Y,X)
    ;     A=X ,           dif(B,X), dif(B,Y)
    ;               A=Y ,               B=Y , dif(Y,X), dif(Y,X)
    ;               A=Y , dif(B,X), dif(B,Y), dif(Y,X)
    ; dif(A,X), dif(A,Y).                     % same result as before
    
    ?- different([4,2,3],[2,3,1]), different([1,2,3],[4,3,1]),
       different([1,4,3],[2,3,1]), different([1,2,3],[2,4,1]),
       different([1,2,4],[2,3,1]), different([1,2,3],[2,3,4]).
    true.                                    % same result as before
    

    Looks alright!

    All in all, not a huge improvement over existing answers, but IMO somewhat more readable code, and a reified version of different/2 as an added bonus!

提交回复
热议问题