different(Xs, Ys) :-
member(X, Xs),
non_member(X, Ys).
different(Xs, Ys) :-
member(Y, Ys),
non_member(Y, Xs).
While this definition usi
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!
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.
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)).
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).
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!