如何返回找到的最大结果?

时间:2015-02-03 19:47:38

标签: prolog max

我有以下事实,描述了世界杯的数据库:

% host(X) <- X is the host country of World Cup
host('South Africa').
% federation (X,Y) <- X is the federation and Y is the numbers of countries in federation X
% qualified for World Cup.
federation('AFC',4).
federation('UEFA', 10).
federation('CAF', 5).
federation('CONMEBOL', 5).
% member_of(X,Y) <- Country Y is member of federation X
member_of('AFC','Australia').
member_of('UEFA', 'England').
member_of('CAF', 'South Africa').
member_of('CONMEBOL','Brazil').
% top(X) <- Country X is top of the World.
top('Brazil').

问题是,我如何找到有资格参加世界杯的国家数量最多的联盟? 我认为我要做的是: solution(X):-federation(X,Y), isMax(Y).
......但我还不知道如何实施它。

3 个答案:

答案 0 :(得分:4)

您的问题可以改写为“查找没有其他联盟与更合格国家/地区的联盟”

该陈述可以用prolog编写:

solution(X):-
  federation(X,Y),    % Find the federation for which
  \+((                % there are no
    federation(_, Z), % other federation with
    Z > Y             % more qualified countries
  )).

答案 1 :(得分:1)

library(aggregate)提供了相应的结构:

solution(X) :- aggregate(max(N,C), federation(C,N), max(_,X)).

?- solution(X).
X = 'UEFA'.

答案 2 :(得分:1)

我在这里作为另一种变体提供,并且不会声称是目前为止提供的最好的变体:

solution(X) :- setof(N-F, federation(F, N), L), reverse(L, [_-X|_]).

setof/3将收集唯一的N-F对,其中F是联盟名称,N是该联盟中有资格参加世界杯的国家数。它们将按照N-F的自然顺序递增,按N然后按Freverse将最大的数字放在列表的第一位,[_-X|_]只选择列表首部的数字。

<小时/> 的附录

应该注意的是,如果数据包含多个最大结果,@ gusbro的方法将生成所有这些结果。但是,aggregate方法不会。上面的setof / reverse方法可以按降序提供所有内容,但如果只选择最大值,则需要一些额外的帮助:

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

solution(X) :-
    setof(N-F, federation(F, N), L),
    reverse(L, [C-Fed|T]),
    pick_top([C-Fed|T], C, X).

然后,这将生成所有顶级联盟:

federation('AFC',4).
federation('UEFA', 10).
federation('CAF', 5).
federation('CONMEBOL', 5).
federation('PDQ', 10).

| ?- solution(X).

X = 'UEFA' ? ;

X = 'PDQ' ? ;

no

<小时/> 使用bagof并避免reverse的替代解决方案:

pick_top([X-F|T], Top) :-
    pick_top(T, X, [F], Top).
pick_top([X-F|T], X, A, Top) :-
    pick_top(T, X, [F|A], Top).
pick_top([Y-_|T], X, A, Top) :-
    Y < X,
    pick_top(T, X, A, Top).
pick_top([Y-F|T], X, _, Top) :-
    Y > X,
    pick_top(T, Y, [F], Top).
pick_top([], _, Top, Top).

solution(X) :-
    bagof(N-F, federation(F, N), L),
    pick_top(L, X).

产生最大值列表:

| ?- solution(X).

X = ['PDQ','UEFA'] ? a

no