Prolog - 返回倒数第二个列表元素

时间:2014-03-19 05:49:40

标签: prolog

在尝试返回用Prolog编写的列表中的倒数第二个元素的问题时感到困惑。这种语言使用起来很有趣,但是我无法绕过它。这就是我所拥有的:

secondLast([X], X).
secondLast(X, [Y], X) :- secondLast(Y, K).    
secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).   
secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).

所以致电secondLast([a, b, c, d], X). X应该等于c

有什么想法吗?

谢谢!

3 个答案:

答案 0 :(得分:5)

可以只是:

secondLast(L, X) :-
    append(_, [X, _], L).

答案 1 :(得分:5)

你应该应用模式匹配:

secondLast([X,_], X).
secondLast([_|T], X) :- secondLast(T, X).

答案 2 :(得分:3)

Sergey和CapelliC为这个问题提供了两个不错的解决方案。让我们来看看原作的错误:

1) secondLast([X], X).
2) secondLast(X, [Y], X) :- secondLast(Y, K).    
3) secondLast(X, [Y|Z], K) :- secondLast(Y, Z, K).   
4) secondLast([X|Z], Ans) :- secondLast(X, Z, Ans).

在Prolog中,由于它是关于定义具有谓词的实体之间的关系,而不是定义函数,因此有助于描述谓词的含义,"某些事情是真的如果其他一些事情是真的"。 Prolog中的 if 表示为:-

我们会看第4条,因为这似乎是你的主要条款。这个说,* Ans[X|Z]的倒数第二个元素,如果Ans是以Z作为头部的X的倒数第二个元素?目前还不清楚这个secondLast的3参数版本意味着什么。但是,如果列表是3个或更多元素,则X似乎变得无关紧要(如第2和第3条所示)。

第1条说明, X是列表[X] 中倒数第二个元素。但是,元素X是列表[X]中的 last only 元素。所以这个条款在逻辑上是不正确的。

第2条有点令人困惑。它在子句K中引入了一个变量,该变量仅使用一次,未在子句中的任何其他位置定义或使用。它也忽略了X,因为如上所述,它已经变得无关紧要,因为它不再是倒数第二个元素的候选者。 Prolog已经给出了关于单例元素KX的警告,这类似于C中的警告,即变量是定义但从未使用过的#34;或者"被分配一个从未使用的值"。条款#3有同样的问题。

在所有这些中,我想我可以看到你想要做的事情,也就是说, Ans[X|Z]的最后一个元素,如果有的话在X 之后的另一个元素,这将是真的,但如果列表[X|Z]是2元素列表,则仅限于正确。换句话说,你的主要条款几乎假定答案最终是X。如果不是,它会尝试在第2和第3条中引入新的候选人Y,但是这个候选人无法回复"原来的主要条款。

我现在回到CapelliC的解决方案,并描述一个人如何做到这一点:

1) secondLast([X,_], X).
2) secondLast([_|T], X) :- secondLast(T, X).

第一个子句说, X是2元素列表中的倒数第二个元素,[X,_] 是真的。而且我们并不关心最后一个元素是什么,所以我们只是称之为_。我们可以称之为Y[X,Y]),但是由于我们不需要或使用Y,Prolog会警告单个变量。

第二个条款说, X是列表[_|T]的倒数第二个元素,如果X是尾部的倒数第二个元素T 。这也是任何3个或更多元素列表的。自基础案例第一部分以来,这很好,它负责2元素列表。第二条将以递归的方式减少到第一条,最后以正确的答案成功。在第二个条款中,如果X取自T,那么我们就不关心列表的头部是什么,因为它变得无关紧要,所以我们使用_作为X在这种情况下的头部(这对应于原始条款#4中的secondLast(L, X) :- append(_, [X, _], L).

谢尔盖的回答:

X

这就是说, L是列表L中倒数第二个元素,如果X是一个以[X,_]作为第一个元素的双元素列表({{ 1}})附加到其他列表的末尾(_)。请再次注意我们将_用于具有值的变量但我们不会#39在这种情况下,关心这些值是什么。因此,例如: 2[1,2,3]的倒数第二个元素,如果[1,2,3] [2,_]附加到其他列表,它是:如果您将[2,3]追加到[1],则会获得[1,2,3]