Reputation: 31
?− count_frequencies ([1 ,1 ,4 ,6 ,8 ,8 ,6 ,2 ,1] , L).
L = [f(1,3),f(4,1),f(6,2),f(8,2),f(2,1)]
my question is about the form of f(1,3) I don't really understand the point. how should i do then output form in Prolog is f(). Thanks!
Upvotes: 0
Views: 37
Reputation: 5509
A term of the form f(X,N)
indicates that item X
has frequency N
. Given an item X
and a list of frequencies F
, the following predicate updates F
to count an occurency of X
, resulting in a new list of frequencies G
:
count(X, [], [f(X,1)]). % add new term
count(X, [f(X,N)|F], [f(X,M)|F]) :- M is N+1. % update existing term
count(X, [f(Y,N)|F], [f(Y,N)|G]) :- X\=Y, count(X, F, G). % continue searching
Running example:
?- count(4,[],A), count(5,A,B), count(4,B,C), count(6,C,D), count(5,D,E), count(4,E,F).
A = [f(4, 1)],
B = [f(4, 1), f(5, 1)],
C = [f(4, 2), f(5, 1)],
D = [f(4, 2), f(5, 1), f(6, 1)],
E = [f(4, 2), f(5, 2), f(6, 1)],
F = [f(4, 3), f(5, 2), f(6, 1)] .
Now, you can use predicate count/3
to define predicate count_frequencies/2
as following:
count_frequencies(Items, Frequencies) :-
loop(Items, [], Frequencies).
loop([], Accumulator, Accumulator).
loop([Item|Items], Accumulator, Frequencies) :-
count(Item, Accumulator, NewAccumulator),
loop(Items, NewAccumulator, Frequencies).
Running example:
?- count_frequencies([1 ,1 ,4 ,6 ,8 ,8 ,6 ,2 ,1] , L).
L = [f(1, 3), f(4, 1), f(6, 2), f(8, 2), f(2, 1)] ;
false.
Alternatively, in SWI-Prolog, you can also use predicate foldl/4
to define a more concise version of the predicate count_frequencies/2
, as following:
another_count_frequencies(Items, Frequencies) :-
foldl(count, Items, [], Frequencies).
Running example:
?- another_count_frequencies([1 ,1 ,4 ,6 ,8 ,8 ,6 ,2 ,1] , L).
L = [f(1, 3), f(4, 1), f(6, 2), f(8, 2), f(2, 1)] ;
false.
Upvotes: 1