Fairly new to Prolog, I'm trying to implement a recursive rule duplicate_nth(N,L1,L2) which takes a 1-based index N, a list L1 and duplicates the Nth value of L1 and returns it in a list L2.
Sample use:
?- duplicate_nth(1, [2,3,4], X).
X = [2,2,3,4]. % expected result
My current code is:
duplicate_nth(N,[H|T],L2) :-
N = 1, % Is `N` equal to 1?
append([H],[H|T],L2). % If so, prepend `H` to `[H|T]`
duplicate_nth(N,H|T,L2) :-
N > 1,
This works if N = 1. It will not, however, work if N > 1 and I am unsure of how to proceed.
No need to worry about implementing recursive predicate(s) the right way!
Simply delegate the "recursive part" to same_length/2, append/3, and length/2:
duplicate_nth(N,Xs0,Xs1) :- % index `N` is 1-based
same_length([_|Xs0],Xs1),
Suffix = [X|_],
append(Prefix,Suffix,Xs0),
length([_|Prefix],N),
append(Prefix,[X|Suffix],Xs1).
Sample query:
?- N = 1, Xs0 = [a,b,c,d], duplicate_nth(N,Xs0,Xs1). N = 1, Xs0 = [a,b,c,d], Xs1 = [a,a,b,c,d] % only solution ; false.
Let's generalize above query and see the solution set grow!
?- Xs0 = [a,b,c,d], duplicate_nth(N,Xs0,Xs1). N = 1, Xs0 = [a,b,c,d], Xs1 = [a,a,b,c,d] % (same solution as before) ; N = 2, Xs0 = [a,b,c,d], Xs1 = [a,b,b,c,d] % (new solution) ; N = 3, Xs0 = [a,b,c,d], Xs1 = [a,b,c,c,d] % (new solution) ; N = 4, Xs0 = [a,b,c,d], Xs1 = [a,b,c,d,d] % (new solution) ; false.
Note that duplicate_nth/3 also works when used "in the other direction".
?- Xs1 = [a,b,b,c,d,d,e], duplicate_nth(N,Xs0,Xs1). N = 2, Xs1 = [a,b,b,c,d,d,e], Xs0 = [a,b,c,d,d,e] ; N = 5, Xs1 = [a,b,b,c,d,d,e], Xs0 = [a,b,b,c,d,e] ; false.
Last, let's run the most general query!
?- duplicate_nth(N,Xs0,Xs). N = 1, Xs0 = [_A], Xs = [_A,_A] ; N = 1, Xs0 = [_A,_B], Xs = [_A,_A,_B] ; N = 2, Xs0 = [_A,_B], Xs = [_A,_B,_B] ; N = 1, Xs0 = [_A,_B,_C], Xs = [_A,_A,_B,_C] ; N = 2, Xs0 = [_A,_B,_C], Xs = [_A,_B,_B,_C] ; N = 3, Xs0 = [_A,_B,_C], Xs = [_A,_B,_C,_C] ; N = 1, Xs0 = [_A,_B,_C,_D], Xs = [_A,_A,_B,_C,_D] ...
Fair enumeration "out-of-the-box"? Perfect!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With