1
votes

I have to find all possible pairs in a list, the following way:

given a list L=[[1,1,1],[1,2,1],[2,1,1],[2,2,1],[3,1,1],[3,2,1]]

[1,1,1] has pairs [1,1],[1,1],[1,1]

[1,2,1] has pairs [1,2],[2,1] because [1,1] was already found

[2,1,1] has pairs [2,1],[2,1] these are not the same because they are located at different positions

[2,2,1] has pairs [2,2] the other pairs have been found

[3,1,1] has pairs [3.1] [3,1]

[3,2,1] has pairs [3,2]

I have a predicate that makes all possible pairs but I doesn't do it this way. I'm new to prolog and I don't know what else to do. This is what I have:

It also returns the number of pairs created

do_pairs(L,PL,N):- do_pairs1(L,[],PL),len(PL,N).
do_pairs1([],L,L) :- !.
do_pairs1([H|T],Pairs,PL):-
     pairs(H,P),
     do_pairs1(T,[P|Pairs],PL)
    .

pairs(L,Pairs):- findall({I-J}, (member(I,L), member(J,L),I=<J), Pairs).
1

1 Answers

1
votes

To solve this problem you have to record the positions of elements in the list and remove these positions only once the pairs have been determined.

:- use_module(library(lists)).

gen_pos_pair(L,pair(P1-E1,P2-E2)):- 
    length(L,N), between(1,N,P1), nth1(P1,L,E1), P1next is P1 +1, 
    between(P1next,N,P2), nth1(P2,L,E2).
gen_pairs([],[]).
gen_pairs([L|Ls],AllPairs):- 
    findall(Pair, gen_pos_pair(L,Pair), Pairs),          
    gen_pairs(Ls,AllPairs1),
    append(Pairs,AllPairs1,AllPairs).
project_positions([],[]).
project_positions([pair(_P1-E1,_P2-E2)|Pairs], [[E1,E2]|PairsNoPos]) :-
    project_positions(Pairs,PairsNoPos).    
correct_pairs(L,R) :-
    gen_pairs(L,All),
    list_to_set(All,S),
    project_positions(S,R).

% auxiliary predicates
writel([]).
writel([X|Xs]) :- write(X), nl,
        writel(Xs).
test(R) :- correct_pairs([[1,1,1],[1,2,1],
                  [2,1,1],[2,2,1],
                  [3,1,1],[3,2,1]],R).

The goal test(X), writel(X). produces the desired output:

[1,1]
[1,1]
[1,1]
[1,2]
[2,1]
[2,1]
[2,1]
[2,2]
[3,1]
[3,1]
[3,2]