我正在尝试在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
(我甚至知道问题在哪里 - > length([T3],P)
这显然是后面列表的长度而不是来自头)。我试图记住我切断了多少元素并在“截断元素数量”= X
时插入P
,但我无法在Prolog中写出来。有什么想法吗?
答案 0 :(得分:3)
% 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>谓词失败长度(列表)+ 1
答案 1 :(得分:2)
让我们在这里陈述你想要的东西。例如,您可以说:“我想在List
元素之后拆分输入Position - 1
,以便我可以在那里插入新元素。”
与append/3
直接交易(DCG会更好):
ins(Element, List, Position, Result) :-
PrefixLength is Position - 1,
length(Prefix, PrefixLength),
append(Prefix, Suffix, List),
append(Prefix, [Element], Temp),
append(Temp, Suffix, Result).
或者您可以说:“我希望在不触及任何内容的情况下浏览List
Position - 1
次内容,然后插入Element
,然后再不再触摸任何内容”。
这次直接转录是:
ins2(Element, List, 1, [Element|List]).
ins2(Element, [Head|Tail], Position, [Head|Result]) :-
Position > 1,
NewPosition is Position - 1,
ins2(Element, Tail, NewPosition, Result).
你也可以说:“我的输入List
是一个等于我的Result
一个的列表,除了它没有Element
作为Position
元素。”并意识到如果你使用swi-prolog,谓词会立即解决这个问题:
ins3(Element, List, Position, Result) :-
nth1(Position, Result, Element, List).
底线是:明确问题是什么,解决方案应该以简单的方式出现。
答案 2 :(得分:2)
TL; DR:要将E
位置I1
插入到列表Es0
中,我们不需要编写递归代码。
相反,我们可以将工作(以及对正确的做法的担忧!)委托给多功能的辅助谓词,所有辅助谓词都是Prolog prologue的一部分。要定义ins_/4
我们写:
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)
请注意,maplist(any_thing, Es, [_|Es0])
相当于same_length(Es, [_|Es0])
。
使用GNU Prolog 1.4.4版(64位)进行示例查询 1,2,3 :
?- 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] ; ...
所有解决方案的公平枚举,好的!
修改:
我按照定义的ins3/4
重复了最常规的查询
关于SWI-Prolog 7.3.11和SICStus Prolog 4.3.2的by @m09 in his answer(两者都以库谓词nth1/4
为特色)。
我很惊讶地发现nth1/4
的底层实现表现出不同的程序语义(w.r.t。"公平枚举")。亲眼看看!
% 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] ... % ...
脚注1:上面显示的所有示例查询都是普遍终止的。
脚注2: GNU Prolog toplevel给出的答案已经打印得很漂亮了。
脚注3:上面提到的代码使用 as-is ,不需要额外的库谓词。
答案 3 :(得分:0)
ins(Element,List,Nth,Result) :-
length([_|L0],Nth),
append(L0,[_|R],List),
append(L0,[Element|R],Result).