对不起,我是Prolog的新手。假设我有一个事实列表说6个事实,第一列数字代表人员ID,第二列代表一个人的胜利数。如果我想找到获胜最多的人,我该怎么做呢?
wins(1, 22).
wins(2, 24).
wins(3, 23).
wins(4, 20).
wins(5, 21).
wins(6, 19).
这样的事情?哈哈老实说,我真的不知道我在做什么
X = wins(_, Xs)
Y = wins(_, Ys)
most wins(X) :- Xs > Ys
答案 0 :(得分:1)
获取该信息的方法不止一种。
most_wins(Id) :-
wins(Id, W), \+ (wins(_, W1), W1 > W).
或者,如果您的Prolog有库(aggregate): -
most_wins(Id) :-
aggregate(max(W, Id), wins(Id, W), max(_, Id)).
或者您可以使用setof / 3
most_wins(Id) :-
setof(N-Id, W^(wins(Id, W), N is -W), [_-Id|_]).
有明显的速度/内存权衡:第一种方式是内存效率,O(1),但时间复杂度为O(N ^ 2),因为它扫描候选集的2倍。第二和第三个(我认为)实际上是等效的,在SWI-prolog的当前实现中,都构建了候选列表(然后是空间中的O(N)),然后及时选择元素-O(N log N)。
如果候选人是事实,请先使用第一个。
编辑另一种方式,从效率角度来看,更好地利用不可回溯的分配。只需扫描候选人,保持最大限度。 Plain Prolog将要求断言/撤回执行此类任务,使其效率相当低。但是许多Prologs有更有效的方法来存储“全球”变量......