试图实现在Prolog中获取列表的第n个元素

时间:2013-12-04 16:40:38

标签: prolog

我在Prolog中非常新,并试图在Prolog中实现获取列表的第n个元素 这是我的代码,但它会抛出错误

element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
   K > 1,
   K1 is K - 1,
   element_at(X,L,K1).

我认为代码右侧第二行的X必须用其他东西替换,但我想不出任何东西。

2 个答案:

答案 0 :(得分:5)

测试时不评估K. 您需要撤销订单

element_at(X,[X|_],1).
element_at(X,[_|L],K) :- element_at(X,L,K1), K is K1 + 1.

答案 1 :(得分:1)

这是一个使用累加器的尾递归版本。使用累加器,它的值在每次调用时都已实例化,因此您可以先递增,然后进行递归。

element_at(X, List, Pos) :-
    element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
    Acc1 is Acc + 1,
    element_at(X, T, Acc1, Pos).

这适用于输入的变量的各种组合,但是如果Pos被接地并且在找到可能的解决方案之后它(以及CapelliC的非尾递归版本)将无限循环,例如:

| ?- element_at(X, L, 3).

L = [_,_,X|_] ? ;
.... loop ....

因此,检查此案例的修改可以避免:

element_at(X, List, Pos) :-
    element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
    (nonvar(Pos) -> Acc < Pos ; true),  % fail if Acc hits ground Pos
    Acc1 is Acc + 1,
    element_at(X, T, Acc1, Pos).

现在你得到:

| ?- element_at(X, L, 3).
L = [_,_,X|_] ? ;
no.

| ?- element_at(X, L, P).
L = [X|_]
P = 1 ? ;
L = [_,X|_]
P = 2 ? ;
L = [_,_,X|_]
P = 3 ? ;
L = [_,_,_,X|_]
P = 4 ? ;
...etc...