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

后端 未结 8 1020
野的像风
野的像风 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 01:03

    Here's another try! We utilize the monotone if-then-else control construct if_/3, in combination with the reified list membership predicate memberd_t/3, and first argument indexing to avoid the creation of useless choice-points.

    different(Xs,Ys) :-
       different_aux(Xs,Ys,Xs,Ys).
    
    different_aux([],[_|_],Xs0,Ys0) :-
       different_aux(Ys0,[],Ys0,Xs0).     % swap Xs/Ys pair
    different_aux([X|Xs],Ys,Xs0,Ys0) :-
       if_(memberd_t(X,Ys0),
           different_aux(Ys,Xs,Ys0,Xs0),  % variant: different_aux(Xs,Ys,Xs0,Ys0)
           true).
    

    First, we run a query that we expect to fail:

    ?- different([1,2,3],[2,3,1]).
    false.
    

    The following queries are similar to the failing query given above; each one has a single "different" item x placed at different indices in the first [1,2,3] or the second list [2,3,1]:

    ?- 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.                                 % all subgoals succeed deterministically
    

    OK! Let's run another (quite general) query that I used in my previous answer:

    ?- different([A,B],[X,Y]).
          A=X ,               B=X , dif(Y,X)
    ;     A=X ,           dif(B,X), dif(Y,B)
    ;               A=Y , dif(B,X), dif(Y,X)
    ; dif(A,X), dif(A,Y).
    

    Compact! A big improvement over what I presented earlier!

    0 讨论(0)
  • 2020-12-07 01:11

    The following bold bounty (+500) was offered not too long ago:

    An idiomatic answer is still missing here. For example, or_t/3 should rather be (;)/3. There is more to it.

    Challenge accepted! This answer is a follow-up to this previous answer.

    1. We use the reified logical connective (;)/3, which can be defined like this:

      ';'(P_1,Q_1,T) :- if_(P_1, T=true, call(Q_1,T)).
      
    2. Next, we define the meta-predicate call_/1. It is useful with reified predicates used in this answer. With its name and semantics, call_/1 follows if_/3, and_/2, and or_/2!

      call_(P_1) :- call(P_1,true).
      
    3. Using (;)/3, call_/1, and some_absent_t/3 we implement different/2:

      different(As,Bs) :- call_((some_absent_t(As,Bs) ; some_absent_t(Bs,As))).
      

    Done! That's it.


    Let's re-run the queries we used in previous answers!

    ?- different([5,4],[1,2]).
    true.
    
    ?- different([1,2,3],[2,3,1]).
    false.
    
    ?- different([4,2,3],[2,3,1]), different([1,4,3],[2,3,1]), different([1,2,4],[2,3,1]),
       different([1,2,3],[4,3,1]), different([1,2,3],[2,4,1]), different([1,2,3],[2,3,4]).
    true.
    

    Same queries, same answers... Looks alright to me!

    0 讨论(0)
提交回复
热议问题