最大列表函数的Prolog问题:非执行与程序

时间:2013-06-20 13:42:03

标签: prolog visual-prolog

我正在尝试在prolog中做一个小项目,用户可以输入一个列表,然后计算列表中的平均值,最大值等等。

到目前为止一切顺利,但在编写max函数时遇到了问题(在列表中找到最大数字)。代码是:

maxN([X],X):-!.
maxN([X|L],X) :- maxN(L,M), X > M.
maxN([X|L],M) :- maxN(L,M), M >= X.

函数本身是单独工作的,但我收到此错误消息:

谓词'forma :: maxN / 2(i,o)',被声明为'procedure',实际上是'nondeterm'forma.pro

这是我在* .cl定义中的谓词:

maxN :(整数* Z,整数U)程序(i,o)。

我无法将其声明为非术语,因为它会导致整个表单出现问题。你能帮助我/暗示如何使它成为一个程序吗?我想我必须在某个地方进行切割,但到目前为止我的尝试都失败了。

P.S。我正在使用Visual Prolog 7.4。

编辑:在尝试将两个规则组合成一个或使用累加器的替代方案之后,我现在得到谓词是'确定'而不是过程。根据我的Prolog指南,这意味着谓词现在没有多个解决方案,而是有机会失败。基本上我到目前为止所做的所有代码变化都让我陷入了'确定'。

2 个答案:

答案 0 :(得分:1)

抱歉,我不知道您正在使用的Prolog方言,我的建议是尝试在第二个句子后添加一个剪辑:

maxN([X|L],X) :- maxN(L,M), X > M, !.

通常,我认为递归过程可以确定性地将其转换为尾递归。不幸的是,这需要添加累加器:

maxN([],A,A).
maxN([X|L],A,M) :- X > A, !, maxN(L,X,M).
maxN([X|L],A,M) :- maxN(L,A,M).

当然,顶级电话会变成

maxN([F|L],M) :- maxN(L,F,M).

答案 1 :(得分:1)

问题是Prolog看到了你的第二和第三条规则之间的选择点。换句话说,你,人类,知道X > MM >= X都不可能都是真的,但Prolog无法推断出这一点。

IMO要做的最好的事情就是用一条规则改写这两条规则:

maxN([X], X) :- !.
maxN([X|L], Max) :- 
   maxN(L, M), 
   X > M -> Max = X
          ; Max = M.

这样就没有一个额外的选择点需要用剪裁来修剪。

按照@ CapelliC的建议,你也可以用累加器重新表示:

maxN([X|Xs], Max) :- maxN_loop(Xs, X, Max).

maxN_loop([], Max, Max).
maxN_loop([X|Xs], Y, Max) :- 
   X > Y -> maxN_loop(Xs, X, Max)
          ; maxN_loop(Xs, Y, Max).