Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate nth value from list

Tags:

list

prolog

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.


1 Answers

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!

like image 179
repeat Avatar answered Feb 17 '26 13:02

repeat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!