列表长度,插入元素

时间:2012-04-08 14:25:16

标签: 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(我甚至知道问题在哪里 - > length([T3],P)这显然是后面列表的长度而不是来自头)。我试图记住我切断了多少元素并在“截断元素数量”= X时插入P,但我无法在Prolog中写出来。有什么想法吗?

4 个答案:

答案 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).