I have a list L = [a, b, c]
and I want to pick all unique non-repeating pairs: [a, b], [a, c], [b, c]
. If I simply use the member function, it, of course, picks every permutation, so I have to have a predicate
pick_pair(List, X, Y) :-
member(X, List),
member(Y, List),
\+ X = Y.
And to access the members I gather all the pairs into a list by using another predicate
unique_pairs(List, Result) :-
findall([X, Y], pick_pair(List, X, Y), Result).
and only then I acess the resulting list, but it generates [[a, b], [a, c], [b, a], [b, c], [c, a], [c, b]]
. I tried to get rid of the pairs that are just a reverse of pairs that were already there by list_to_set
but [a, b]
and [b, a]
do not unify on default, so they're considered to be not equal and therefore belong to the set. I would somehow need to overload the unification for that function or something like that.
My question is:
Can we just access pairs in a list? Something like my_pairs(X, Y, L)
which would assign the pair elements directly to X
and Y
. And if there is no such predicate, how can we make a list of the unique pairs so that we can access its elements by using member(X, List)
?
The problem is, by the way, equivalent to getting all the combinations of length two.
Can use a custom variant of select
:
unique_pairs(L, E1, E2) :-
select_forward(E1, L, L0),
member(E2, L0).
select_forward(E, [H|T], F) :-
select_forward_(T, H, E, F).
select_forward_(T, H, H, T).
select_forward_([H|T], _, E, F) :-
select_forward_(T, H, E, F).
Result in swi-prolog:
?- unique_pairs([a,b,c], E1, E2).
E1 = a,
E2 = b ;
E1 = a,
E2 = c ;
E1 = b,
E2 = c ;
false.