Geperd
Geperd

Reputation: 15

Prolog, how to add items from one list to second

Good Morning
I have a list in following format:

[(1-4),(2-4), (3-4)] 

I'd like to change it to:

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

I have tried 2 programs:

changeList([], Z) :- 
    write(Z).
changeList([(A-B)|T], Z) :-
    append([A], Z, Y),
    append([B], Y, X),
    changeList(T, X).

and the second one:

changeList([],Z) :-
    write(Z).
changeList([(X-Y)|T], Z) :-
    W = [X|Z],
    C = [Y|W],
    changeList(T,C).

Sadly the result is always: [4,3,4,2,4,1|_38]. Where do i make a mistake?

Upvotes: 1

Views: 68

Answers (2)

joel76
joel76

Reputation: 5645

foldl/4 is a friend for you :

changeList(In, Out) :-
    foldl(reverse_one, In, [], Out).

reverse_one((X-Y), In, [Y,X|In]).

Example :

?- changeList([(1-4),(2-4),(3-4)],Out).
Out = [4, 3, 4, 2, 4, 1].

Upvotes: 0

damianodamiano
damianodamiano

Reputation: 2662

You can solve your problem with different metods. If you want to get the list in reverse order, you need a further input variable which is an empty list. Using your code you can write:

changeList([],Z,Z).
changeList([(A-B)|T],Acc,Z) :-
    append([A], Acc, Y),
    append([B], Y, X),
    changeList(T,X,Z).

?- changeList([(1-4),(2-4),(3-4)],[],Z).
Z = [4, 3, 4, 2, 4, 1]

You can avoid the use of append/3 in this way:

myReverse([],Z,Z).
myReverse([(A-B)|T],Acc,Z):- 
    myReverse(T,[B,A|Acc],Z).

?- myReverse([(1-4),(2-4),(3-4)],[],Z).
Z = [4, 3, 4, 2, 4, 1]

You have another solution which is to print the list in an ordered way, then reverse it using built-in predicate (in SWI) reverse/2:

changeListOrd([],[]).
changeListOrd([(A-B)|T], [A,B|TL]):-
    changeListOrd(T,TL).
change(L,Lout):-
    changeListOrd(L,L1),
    reverse(L1,Lout).

?- change([(1-4),(2-4),(3-4)],Z).
Z = [4, 3, 4, 2, 4, 1]

I suggest you to go with the second solution (myReverse/3) so you don't need both append/3 and reverse/2.

Upvotes: 1

Related Questions