Holly Marie Batchelor
Holly Marie Batchelor

Reputation: 113

Writing an existing list to a new list in Prolog

I'm trying to write a list inputted by the user to a new list in Prolog. I have figured out how to do it using a reverse method and it works fine. My problem is that I need it to stop at the element the user inputs along with the list (so I can repeat this value again before adding the remainder of the list). For example if I was to input

repeat_nth(3, [a,b,c,d,e], X). 

its output should be

X = [a,b,c,c,d,e].

When I try to introduce a variable 'N' to count until the element to be repeated prolog just tells me 'no'. Here is my code:

new_list(N,[H|T],A,L2):- N > 0,
    N1 is N - 1,
    new_list(N1,T,[H|A],L2). 
new_list(0,[],A,A).
repeat_nth(N,L1,L2):- new_list(N,L1,[],L2).

Upvotes: 3

Views: 402

Answers (2)

lurker
lurker

Reputation: 58274

The predicate can be built up from a couple of cases. If you think about them logically first and express them in a sentence or two, it can help determine the clauses.

Base case: the list, [H|T] with the first element (H, element number 1) repeated is a list where the head (H) appears twice. The tail (T) remains the same:

repeat_nth(1, [H|T], [H,H|T]).

Recursive case: for N > 1, to repeat the Nth term of a list [H|T], I copy over the head (H) and then repeat the (N-1)st term (N1 is N-1) of the tail (T) of the first list, and that is the tail of the second (T1):

repeat_nth(N, [H|T], [H|T1]) :-
    N > 1,
    N1 is N-1,
    repeat_nth(N1, T, T1).

The above two clauses are all that's needed. One of your attempts described in your comments was very close! The error was in that last line of the second clause. You tried:

repeat_nth(N1, [H|T], [H|T1]).

So you carried along the H which was incorrect. H is already taken care of in the head of the clause, and the purpose of this new call is to take care of the tails (as the description of the recursive case indicates).

Upvotes: 2

CapelliC
CapelliC

Reputation: 60034

...
Call: (10) new_list(0, [d, e], [c, b, a], _G2728)
Call: (11) 0>0
Fail: (11) 0>0
...

Seems your code is missing the base case. It's fairly clear that [d,e] cannot match [].

Upvotes: 0

Related Questions