我需要在列表中找到最大偶数。例如
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。我不知道这个变量第一次可以分配给这个变量的值是多少。
答案 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).