5

I am attempting to get my arms around some basic prolog but struggling a bit in the process. In specific - I am trying to get through a list of items and copy it, item by item into a new list. I can get it to reverse, but I am finding it trickier doing it without reversing.

Ive been trying the following -

copy(L,R) :- accCp(L,R).

accCp([],R).
accCp([H|T],R) :- accCp(T,H).

When i run a trace on this - i can see the individual items being copied across, but they get 'lost', and dont form a growing list (at R, as i was hoping). How could i achivie this?

Many thanks

v_a_bhatia
  • 125
  • 1
  • 3
  • 12

2 Answers2

8

Your base case needs to set the copy list to empty when the original list is empty. Then, the recursive case needs to take H from list L and add it to the head of list R:

copy(L,R) :- accCp(L,R).
accCp([],[]).
accCp([H|T1],[H|T2]) :- accCp(T1,T2).

When you call copy, it works its way down to the base case, where it sets R to an empty list. Then, as it works back up, it keeps appending the head H of known list [H|T1] to the beginning of variable list [H|T2]. It does that until the original case is reached, at which point R contains a full copy of L.

Kaleb Brasee
  • 51,193
  • 8
  • 108
  • 113
  • Thank you, so if i understand the trace correctly - its runs down through the list until accCp([],_) is true, in which case _ is replaced with [] and then as it backs up again, it ensured that the second '[]' is always equal to the first one? is that the logic? Many thanks! – v_a_bhatia Dec 16 '09 at 02:15
  • Yep, that is correct -- in the recursive case it takes H from L and adds it to the head of R. And since both lists were equal (empty) in the base case, they'll end up equal when the function is done. – Kaleb Brasee Dec 16 '09 at 02:35
  • It would be good if the answer also discussed what will happen if the input list contains variables, e.g. shouldn't the copy be independent from the original (as with copy_term/2). Also, how should open lists be copied? The test case could be e.g. "copy([A, B, c, A | X], L)" – Kaarel Dec 26 '09 at 22:24
2

Very simple approach would be:

clone1(X,X).

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

Here's an expressive approach for the list handling. You want to copy or clone a list. My approach is add every element from the list to want to copy to another list and return another list.

clone([],[]).
clone([H|T],[H|Z]):- clone(T,Z).

OUTPUT

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

?- clone([a,b,c,d],Z).
   Z=[a,b,c,d]

?- clone([ [a,1,2] , [b,2,3] , [c,3,4] ],Z).
   Z = [[a, 1, 2], [b, 2, 3], [c, 3, 4]]

This works for every kind of list.

Ch3steR
  • 20,090
  • 4
  • 28
  • 58