在列表的第1,第2,第4,第8 ......元素之后插入给定值v。 (序言)

时间:2014-10-25 21:53:46

标签: prolog

我正在尝试在SWI Prolog中解决此问题,我的代码目前看起来像这样:

insert(L1,X,L2):-
    COUNTER = 1,
    NEXT    = 1,
    insert_plus(L1,COUNTER,NEXT,X,L2).

insert_plus([],_,_,_,[]).
insert_plus([H|T],COUNTER,NEXT,X,[H|T1]) :-    % don't insert
    COUNTER \= NEXT,
    insert_plus(T,COUNTER+1,NEXT,X,T1).
insert_plus([H|T],COUNTER,NEXT,X,[H|[X|T]]) :- % DO insert
    COUNTER = NEXT, 
    insert_plus(T,COUNTER+1,NEXT*2,X,T).

有人可以解释为什么这并不总是按预期工作?

?- insert([1,2,3,4,5,6,7],9,X).
X = [1,9,2,3,4,5,6,7].            % BAD! expected: `X = [1,9,2,9,3,4,9,5,6,7]`

2 个答案:

答案 0 :(得分:1)

Prolog没有评估表达,它证明了关系。因此必须明确地进行算术运算。这里

...
insert_plus(T, COUNTER+1, NEXT, X, T1).

你需要

...
SUCC is COUNTER+1,
insert_plus(T, SUCC, NEXT, X, T1).

同样的问题 - 包括COUNTER和NEXT - 出现在最后一条规则中。

答案 1 :(得分:1)

您需要更改的绝对最低要求是:

insert_plus([],_,_,_,[]).
insert_plus([H|T],COUNTER,NEXT,X,[H|T1]) :-
    COUNTER =\= NEXT,                             % `(=\=)/2` arithmetic not-equal
    insert_plus(T,COUNTER+1,NEXT,X,T1).
insert_plus([H|T],COUNTER,NEXT,X,[H|[X|T1]]) :-   % use `T1`, not `T`
    COUNTER =:= NEXT,                             % `(=:=)/2` arithmetic equal
    insert_plus(T,COUNTER+1,NEXT*2,X,T1).         % use `T1` (as above)

示例查询:

?- insert([1,2,3,4,5,6,7],9,X).
X = [1,9,2,9,3,4,9,5,6,7].                        % expected result

除了上述更改,我建议您注意@CapelliC给出的 in his answer关于使用内置Prolog谓词(is)/2的算术表达式评估...

......或者更好的是,使用