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
并且我不确定如何继续,它将不起作用。
答案 0 :(得分:2)
无需担心以正确的方式实现递归谓词!
只需将“递归部分”委托给same_length/2
,append/3
和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).
示例查询:
?- 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) :-
!.
List2
在List1
函数中编写,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(_,[],[]).