List 列表长度,插入元素
我正试图用Prolog编写一个程序,它将把一个元素插入到某个位置,例如List 列表长度,插入元素,list,prolog,List,Prolog,我正试图用Prolog编写一个程序,它将把一个元素插入到某个位置,例如 ?- ins(a, [1,2,3,4,5], 3, X). X = [1,2,a,3,4,5]. 我有以下代码: ins(X,[H|T],P,OUT) :- length([T3],P), concatenate(X,[H],T), ins(...). 问题是它从后面在给定索引中插入元素X(我甚至知道问题在哪里->长度([T3],p),这显然是列表从后面开始的长度,而不是从开头开始的长度)。我试着记住
?- ins(a, [1,2,3,4,5], 3, X).
X = [1,2,a,3,4,5].
我有以下代码:
ins(X,[H|T],P,OUT) :-
length([T3],P),
concatenate(X,[H],T),
ins(...).
问题是它从后面在给定索引中插入元素X
(我甚至知道问题在哪里->长度([T3],p),这显然是列表从后面开始的长度,而不是从开头开始的长度)。我试着记住当“截断元素的数量”=P
时,我截断并插入了多少元素,但我不能在Prolog中真正写出这一点。有什么想法吗
% ins(Val,List,Pos,Res)
ins(Val,[H|List],Pos,[H|Res]):- Pos > 1, !,
Pos1 is Pos - 1, ins(Val,List,Pos1,Res).
ins(Val, List, 1, [Val|List]).
如果Pos=0或Pos>length(List)+1,则谓词将失败。让我们在这里说明您想要什么。例如,您可以说:“我想在
位置-1
元素之后拆分我的输入列表
,以便在那里插入一个新元素”
与append/3
直接交易(顺便说一句,DCG会更好):
或者你可以说:“我想在不碰任何东西的情况下浏览列表中的元素
位置-1
次,然后插入元素
,然后再也不碰任何东西。”
这一次的直接交易是:
ins2(Element, List, 1, [Element|List]).
ins2(Element, [Head|Tail], Position, [Head|Result]) :-
Position > 1,
NewPosition is Position - 1,
ins2(Element, Tail, NewPosition, Result).
您也可以这样说:“我的输入列表
是一个列表,它等于我的结果
一,除了它没有我的元素
作为位置
第四个元素。”并且要意识到,如果使用swi prolog,谓词会立即解决这个问题:
ins3(Element, List, Position, Result) :-
nth1(Position, Result, Element, List).
底线是:清楚地说明问题所在,解决方案应该简单明了。TL;DR:要将项目
E
插入列表Es0
中的位置I1
,我们不需要编写递归代码
ins(Element,List,Nth,Result) :-
length([_|L0],Nth),
append(L0,[_|R],List),
append(L0,[Element|R],Result).
相反,我们可以将这项工作(以及对如何正确完成这项工作的担忧)委托给多功能辅助谓词,所有这些都是任务的一部分。要定义ins\u4
,我们写:
ins_(E, Es0, I1, Es) :-
maplist(any_thing, Es, [_|Es0]),
append(Prefix, Suffix, Es0),
length([_|Prefix], I1),
append(Prefix, [E|Suffix], Es).
any_thing(_, _). % auxiliary predicate (used above)
让我们不要忘记最一般的查询
?- ins(X, Es0, I1, Es).
Es0 = [], I1 = 1, Es = [X]
;
Es0 = [A], I1 = 1, Es = [X,A]
; Es0 = [A], I1 = 2, Es = [A,X]
;
Es0 = [A,B], I1 = 1, Es = [X,A,B]
; Es0 = [A,B], I1 = 2, Es = [A,X,B]
; Es0 = [A,B], I1 = 3, Es = [A,B,X]
;
Es0 = [A,B,C], I1 = 1, Es = [X,A,B,C]
; Es0 = [A,B,C], I1 = 2, Es = [A,X,B,C]
; Es0 = [A,B,C], I1 = 3, Es = [A,B,X,C]
; Es0 = [A,B,C], I1 = 4, Es = [A,B,C,X]
;
Es0 = [A,B,C,D], I1 = 1, Es = [X,A,B,C,D]
; ...
脚注1:上面显示的所有示例查询均以通用方式终止。
注2:GNU Prolog toplevel给出的答案已经打印了一点。
脚注3:上面给出的代码按原样使用,不需要额外的库谓词。pos>1,newPos是p-1,wuaa这就是我要找的:)thx a lot虽然这段代码可以回答这个问题,但最好解释一下它是如何解决问题的以及为什么要使用它。从长远来看,只使用代码的答案是没有用的。查询
?-ins_1;(a[1,2,3,4,5],3[1,2,a,3,4,5])。
失败,应该会成功。如果查询?-ins_(a[1,2,3,4,5],3[1,2,a,4,5])。
成功,则应失败。要修复此错误,您需要删除4个字符:)
?- ins_(X, [a,b,c,d,e], N1, Xs).
N1 = 1, Xs = [X,a,b,c,d,e]
; N1 = 2, Xs = [a,X,b,c,d,e]
; N1 = 3, Xs = [a,b,X,c,d,e]
; N1 = 4, Xs = [a,b,c,X,d,e]
; N1 = 5, Xs = [a,b,c,d,X,e]
; N1 = 6, Xs = [a,b,c,d,e,X]
; false.
?- ins_(X, [a,b,c,d,e], 3, Xs).
Xs = [a,b,X,c,d,e]
; false.
?- ins_(X, Xs0, 3, [a,b,c,d,e]).
X = c, Xs0 = [a,b,d,e]
; false.
?- ins(X, Es0, I1, Es).
Es0 = [], I1 = 1, Es = [X]
;
Es0 = [A], I1 = 1, Es = [X,A]
; Es0 = [A], I1 = 2, Es = [A,X]
;
Es0 = [A,B], I1 = 1, Es = [X,A,B]
; Es0 = [A,B], I1 = 2, Es = [A,X,B]
; Es0 = [A,B], I1 = 3, Es = [A,B,X]
;
Es0 = [A,B,C], I1 = 1, Es = [X,A,B,C]
; Es0 = [A,B,C], I1 = 2, Es = [A,X,B,C]
; Es0 = [A,B,C], I1 = 3, Es = [A,B,X,C]
; Es0 = [A,B,C], I1 = 4, Es = [A,B,C,X]
;
Es0 = [A,B,C,D], I1 = 1, Es = [X,A,B,C,D]
; ...
% SICStus Prolog 4.3.2 % SWI Prolog 7.3.11
% %
?- ins3(X, Es0, I1, Es). % ?- ins3(X, Es0, I1, Es).
I1 = 1, Es0 = [], Es = [X] % I1 = 1, Es = [X|Es0]
; % ; I1 = 2, Es0 = [_A|_Z],
I1 = 1, Es0 = [_A], Es = [X,_A] % Es = [_A,X|_Z]
; I1 = 2, Es0 = [_A], Es = [_A,X] % ; I1 = 3, Es0 = [_A,_B|_Z],
; % Es = [_A,_B,X|_Z]
I1 = 1, Es0 = [_A,_B], Es = [X,_A,_B] % ; I1 = 4, Es0 = [_A,_B,_C|_Z],
; I1 = 2, Es0 = [_A,_B], Es = [_A,X,_B] % Es = [_A,_B,_C,X|_Z],
; I1 = 3, Es0 = [_A,_B], Es = [_A,_B,X] % ; I1 = 5, Es0 = [_A,_B,_C,_D|_Z],
; % Es = [_A,_B,_C,_D,X|_Z]
... % ...