You're actually quite close with count_elt/3
, but you need more non-determinism. In short, you need to find a way to express count_elt/3
with fewer cuts, because right now you get this:
?- count_elt([a,b,a,a,c,b,d,e,a,f], Y, X).
Y = a,
X = 4.
And what you want to get is this:
?- count_elt([a,b,a,a,c,b,d,e,a,f], Y, X).
Y = a,
X = 4 ;
Y = b,
X = 2 ;
Y = c,
X = 1 ;
...
Y = f,
X = 1 ;
false.
From there you're just trying to find the solutions with the maximum value, which you can do with setof/3
or a logical expression or using the aggregate
library. So fix count_elt/3
first and go from there.
Edit: some general remarks:
- You can write
[H1|[H2|T]]
as [H1,H2|T]
, which is a bit more clear.
listMode/2
should probably be returning the item in the second position rather than the count. Since you need the count to do this procedure, you're probably going to need to make a listMode/3
or listMode/5
helper to manage your state during the recursion.
Edit: solution
Since @MaDu_LK has decided to show the solution, even though this is most likely homework, I thought I'd share mine, using @false's reified equality predicate:
count_of([], _, 0).
count_of([H|Rest], E, N1) :-
equality_reified(H, E, Bool),
count_of(Rest, E, N0),
(Bool == true -> N1 is N0 + 1 ; N1 = N0).
frequency(L, I, N) :-
sort(L, LSorted),
member(I, LSorted),
count_of(L, I, N).
mode(L, X) :-
frequency(L, X, NMax),
\+ (frequency(L, _, NBigger),
NMax < NBigger).
This has somewhat more pleasing performance properties:
% MaDu_LK
?- time(get_mode([a,b,c,a,b,c,a,a,b,c,a,d,b], X)).
% 2,811 inferences, 0.000 CPU in 0.000 seconds (100% CPU, 7117429 Lips)
X = a.
% mine
?- time(mode([a,b,c,a,b,c,a,a,b,c,a,d,b], X)).
% 217 inferences, 0.000 CPU in 0.000 seconds (98% CPU, 3144928 Lips)
X = a ;
% 195 inferences, 0.000 CPU in 0.000 seconds (97% CPU, 3305085 Lips)
false.
The other solution also produces only one mode, even if the list is multimodal:
% MaDu_LK
?- get_mode([a,a,b,b,c], X).
X = a.
% mine
?- mode([a,a,b,b,c], X).
X = a ;
X = b ;
false.
Food for thought.