列表中的第n个值重复

时间:2014-03-23 21:04:10

标签: list prolog

Prolog相当新,我正在尝试实现一个递归规则duplicate_nth(N,L1,L2),该规则采用从1开始的索引N,列表L1并复制{{N}的第N个值1}}并将其返回到列表L1中。

样品使用:

L2

我目前的代码是:

?- duplicate_nth(1, [2,3,4], X).
X = [2,2,3,4].                  % expected result

这适用于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, 。但是,如果N = 1并且我不确定如何继续,它将不起作用。

2 个答案:

答案 0 :(得分:2)

无需担心以正确的方式实现递归谓词!

只需将“递归部分”委托给same_length/2append/3length/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).

示例查询:

?- 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.

让我们概括一下上面的查询,看看解决方案集增长!

?- 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.

请注意,duplicate_nth/3在“向另一个方向”使用时也有效。

?- 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.

最后,让我们运行最常见的查询!

?- 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]
...

公平的枚举“开箱即用”?完美!

答案 1 :(得分:0)

列表中几乎所有函数都具有相同的结构。一个基本案例:

function(FixedValues,List1,List2) :-
    !.

List2List1函数中编写,FixedValues是一组基于参数的参数。

一个归纳案例:

function(Values,[H|T],[H2|T2]) :-
    other_function(H,H2), %transform H into H2
    ValuesNext is Values-1, %or some other function
    function(ValuesNext,T,T2).

!是" cut"并且如果满足第一个条件,则阻止Prolog执行其他谓词定义。


应用于此问题,请尝试:

duplicate_nth(1,[H|T],[H,H|T]) :- %base case
    !.

duplicate_nth(N,[H|T],[H|T2]) :- %inductive case
    N1 is N-1,
    duplicate_nth(N1,T,T2).

在大多数情况下,您需要使程序更安全,因为N可能超出范围(小于或等于零,或大于列表的长度。)

在这种情况下,请添加:

duplicate_nth(_,[],[]).