Jessica Simoes
Jessica Simoes

Reputation: 33

How do I change position of two elements in a list(PROLOG)

predicate change_pos(E1, E2,Lin,Lout).

The Lin has any number of elements, and I need to change all occurences of E1 to E2, and vice-versa. And return in Lout.

I was thinking to do something like this:

change(X, Y, [], []).
change(X, Y, [X|L], [Y,L1]):- change(X,Y,L,L1).
change(X, Y, [Z|L], [Z,L1]:- X \== Z, change(X,Y,L,L1).

But this way is not swiping two number of the list

Upvotes: 1

Views: 818

Answers (2)

lurker
lurker

Reputation: 58234

I'm supposing, since this is homework, it's an exercise to learn list processing and recursion. But in Prolog, a common tool for processing each term in turn in a list is maplist:

% Rule for changing one element
change_element(X, Y, X, Y).
change_element(X, Y, Y, X).
change_element(X, Y, Z, Z) :- dif(X, Z), dif(Y, Z).

% Rule for changing a list
change(X, Y, L1, L2) :-
    maplist(change_element(X, Y), L1, L2).

Which yields:

?- change(a, b, [a,b,c,b,a], L).

L = [b, a, c, a, b] ? ;

no
?-


For a determinate solution, you can use if_/3:

change1(X, Y, A, B) :-
    if_(=(Y, A), B = X, A = B).
change2(X, Y, A, B) :-
    if_(=(X, A), B = Y, change1(X, Y, A, B)).

change(X, Y, L1, L2) :- maplist(change2(X, Y), L1, L2).

Which yields:

?- change(a, b, [a,b,c,b,a], L).

L = [b, a, c, a, b].

?-

Upvotes: 4

tas
tas

Reputation: 8140

You're almost there. Your base case (the empty lists) and your second rule (swap X for Y) are basically fine (apart from the details pointed out in the comments). However, you are missing a rule for vice-versa (swap Y for X). And in your last rule you likely want to make sure that Z differs not only from X but also from Y, otherwise Z would be subject to rule two or three.

change(X, Y, [], []).
change(X, Y, [X|L], [Y|L1]) :-
   change(X,Y,L,L1).
change(X, Y, [Y|L], [X|L1]) :-   % <- vice versa case
   change(X,Y,L,L1).
change(X, Y, [Z|L], [Z|L1]) :-
      dif(X,Z),                  % <- neither X=Z
      dif(Y,Z),                  % <- nor vice versa
      change(X,Y,L,L1).

Here are some example queries. What does [1,2,3,4] look like after swapping 1 with 2 and vice versa?

   ?- change(1,2,[1,2,3,4],L).
L = [2,1,3,4] ? ;
no

What did [2,1,3,4] look like before swapping 1 with 2 and vice versa?

   ?- change(1,2,L,[2,1,3,4]).
L = [1,2,3,4] ? ;
no

Which elements have been swapped in [1,2,3,4] if the resulting list is [2,1,3,4] ?

   ?- change(X,Y,[1,2,3,4],[2,1,3,4]).
X = 1,
Y = 2 ? ;
X = 2,
Y = 1 ? ;
no

Upvotes: 2

Related Questions