zhang rui
zhang rui

Reputation: 31

The form of Result in Prolog

?− 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

Answers (1)

slago
slago

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

Related Questions