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.
ADDENDUM
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
An alternative solution using
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