Prolog在列表中找到最大偶数

时间:2013-11-16 10:04:04

标签: list for-loop numbers prolog

我需要在列表中找到最大偶数。例如

goal: maxEVEN([4,10,-2,-1,23],M).
M=10.

我写了以下代码:

maxeven([],M).
maxeven([X|R],M):- Rest is X mod 2,
                    isRest(Rest, X, M, R).
isRest(0,X,M,[List]):- X > M,
                    maxeven(List,X).
isRest(0,X,M,[List]):- X < M,
                    maxeven(List,M).
isRest(Rest,X,M,[List]):- maxeven(List,M).

它会抛出每个循环成员并检查它是否是偶数,如果是,那么检查它是否比已经指定的M值更具创造性。 问题是,对于第一个调用isRest谓词,M的值为空,这就是为什么它总是返回false。我不知道这个变量第一次可以分配给这个变量的值是多少。

2 个答案:

答案 0 :(得分:1)

有一些简单的方法:首先寻找第一个偶数,初始化M,或者以M未绑定开始,并使用var / 1检查状态。

但我认为您的代码还有其他问题。这是不寻常的语法:

isRest(0,X,M,[List]):-..

[List]这是一个元素的列表,因此我无法看到它如何适合您的算法。也许问题来自于您的代码比需要的更复杂。如果我们假设,当没有偶数时,maxeven / 2可以失败,可以很简单

maxeven([X|Xs], M) :-
  0 is X mod 2, % fail if not even
  ( maxeven(Xs, T), T > X, !, M = T ; M = X).
maxeven([_|Xs], M) :-
  maxeven(Xs, M).

这是如何工作的:当X是偶数时,尝试看看是否有其他的甚至在X中,并进行比较,但如果没有其他甚至存在(例如,当X是最后一个)时,保持X.否则,当X不均匀时,搜索尾Xs ......

看看能否理解为什么需要切割,然后将其移动到其他地方以更好地理解Prolog控制流程......这不是很直观......

如果您对Prolog感兴趣,请不要忘记研究它的库:maxeven / 2可以像

一样简单
maxeven(Xs, M) :- setof(X, (member(X, Xs), 0 is X mod 2), Evens), last(Evens, M).

答案 1 :(得分:1)

这是一个尾递归版本:

maxeven([X|T], MaxEven) :-
    0 is X mod 2, !,
    maxeven(T, X, MaxEven).
maxeven([_|T], MaxEven) :-
    maxeven(T, MaxEven).
maxeven([X|T], LastMax, MaxEven) :-
    0 is X mod 2, !,
    M is max(X, LastMax),
    maxeven(T, M, MaxEven).
maxeven([_|T], LastMax, MaxEven) :-
    maxeven(T, LastMax, MaxEven).
maxeven([], LastMax, LastMax).