Reputation: 6469
I have the following facts, which describes the database of a World Cup:
% 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').
The question is, how do I find the federation that the number of Countries qualified to World Cup is largest?
What I think I'm gonna do is something like:
solution(X):-federation(X,Y), isMax(Y).
... but I don't know how to implement it yet.
Upvotes: 0
Views: 307
Reputation: 58304
I offer here as another variation and won't claim is the best of those offered so far:
solution(X) :- setof(N-F, federation(F, N), L), reverse(L, [_-X|_]).
The setof/3
will gather unique pairs of N-F
where F
is the federation name, and N
is the number of countries in that federation qualified for World Cup. They will be in increasing order according to the natural order of N-F
, which is by number N
then by F
. The reverse
puts the largest number first in the list, and [_-X|_]
just selects the number from the head of the list.
It should be noted that if the data contains more than one maximum result, @gusbro's approach will generate all of them. However, the aggregate
method will not. The setof
/reverse
method above can provide everything in descending order of magnitude, but needs a little extra help if only the maximums are to be picked out:
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).
This will then generate all of the top federations:
federation('AFC',4).
federation('UEFA', 10).
federation('CAF', 5).
federation('CONMEBOL', 5).
federation('PDQ', 10).
| ?- solution(X).
X = 'UEFA' ? ;
X = 'PDQ' ? ;
no
bagof
and avoiding 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).
Which produces a list of maximums:
| ?- solution(X).
X = ['PDQ','UEFA'] ? a
no
Upvotes: 1
Reputation: 60034
library(aggregate) offers the appropriate constructs:
solution(X) :- aggregate(max(N,C), federation(C,N), max(_,X)).
?- solution(X).
X = 'UEFA'.
Upvotes: 1
Reputation: 22585
Your question can be reworded as "Find the federation for which there are no other federation with more qualified countries"
That statement can be written in prolog as:
solution(X):-
federation(X,Y), % Find the federation for which
\+(( % there are no
federation(_, Z), % other federation with
Z > Y % more qualified countries
)).
Upvotes: 4