Prolog在列表中查找Kth元素

时间:2013-10-31 19:04:13

标签: list prolog

我正在尝试在prolog中编写一个谓词来查找列表中的Kth元素。 例如:

?- element_at(X,[a,b,c,d,e],3).
X = c

我的代码如下

k_ele(X,[X|_],1).
k_ele(X,[_|T],Y) :- Y > 1,Y is Y - 1, k_ele(X,T,Y).

但没有用,我在互联网上找到了解决方案

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

除了使用一个额外的变量K1之外,它与我的逻辑相同。

我的代码出了什么问题,为什么我需要另一个变量?

3 个答案:

答案 0 :(得分:3)

您的代码不起作用的原因是统一不是一项任务。当你说

Y is Y - 1

您正试图将Y的值与Y-1的值统一,这在数学上是不可能的。这与说4 is 31001 is 1000大致相同。整个条件失败,导致无法在列表中找到元素。

您在互联网上找到的固定解决方案引入了一个单独的变量K1,该变量与K - 1统一。这是非常可行的:K1获取K-1计算的值,条件成功,并且子句移动到递归调用部分。

答案 1 :(得分:2)

因为prolog中的变量是一次性写入的生物。已经[赋值]一个非变量值,它不再是变量。从此以后就是这个价值。与更多...传统...编程语言不同,一旦绑定,重新分配prolog变量的唯一方法是回溯分配并撤消它。

应该注意的是,变量可以与另一个变量统一:给出类似

的谓词
foo(X,Y) :- X = Y .

等等

shazam(X,Y) :- bar(X,Y) , X = 3.

将导致X和Y都为3.统一后,X和Y都是相同的变量,尽管名称不同。

答案 2 :(得分:1)

我想你正在使用这个链接的练习:

http://www.ic.unicamp.br/~meidanis/courses/problemas-prolog/

请注意,在我看来,原始解决方案也不是最好的。

例如,查询:

element_at(X,[a,b,c],Y).
即使有3个解决方案,

也会崩溃:

  • X = a,Y = 1;
  • X = b,Y = 2;
  • X = c,Y = 3;

我相信以另一种方式写作:

element_at(H, [H | _], 1).
element_at(H, [_ | T], N) :- element_at(H, T, NMinus1), N is NMinus1 + 1.

会给出更好的结果。由于无法应用最后一次调用优化,因此效率较低,但逻辑变得更加通用。