Calculul histogramei unei liste in Prolog
/*****************************************
* Determinarea numarului de aparitii ale elementelor unei liste
* Paul Mateescu, grupa 309-Informatica, an III-ZI, 2009.
* Facultatea de Matematica si Informatica, Universitatea Spiru Haret Bucuresti.
******************************************
* Problema:
* Dandu-se o lista de numere, sa se furnizeze intr-o alta lista frecventa lor de aparitie:
* Exemplu de utilizare:
* frecv([1, 2, 2, 7, 4, 4, 2, 3, 1, 3, 1, 1, 9, 7, 5], X)
* va genera solutia unica X = [f(1, 4), f(2, 3), f(7, 2), f(4, 2), f(3, 2), f(9, 1), f(5, 1)]
*
*/
trail=4000
domains
item = integer
iteml = item*
integerl = integer*
fr = f(item, integer)
frl = fr*
predicates
run(integer, iteml, frl) % genereaza o lista de nr aleatoare si calculeaza frecventele de aparitie
randomlist(integer, iteml) % genereaza o lista de numere aleatoare in intervalul 0..9
frecv(iteml, frl) % initiaza calculul frecventei, serveste drept interfata cu utilizatorul
frecvh(item, iteml, integer, integer, iteml, iteml, frl) % functie ajutatoare care realizeaza calculul propriu-zis al frecventei
clauses
% Un predicat care genereaza o lista de lungime ceruta, apoi calculeaza frecventa de aparitie a elementelor:
% (i, o, o)
% Notand run(N, L, F), semnificatia argumentelor este:
% N - numarul dorit de elemente al listei
% L - lista de N elemente aleatoare
% F - lista de frecvente de aparitii ale elementelor listei L
run(N, L, F) :-
randomlist(N, L),
frecv(L, F).
/***************************************************************/
% Un predicat care genereaza o lista cu mai multe elemente alese aleatoriu in intervalul 0..9, util pentru testare:
% (i, o)
% Notand randomlist(N, L), semnificatia argumentelor este:
% N - numarul dorit de elemente din lista
% L - Lista cu N elemente
randomlist(0, []).
randomlist(N, [H|T]) :-
N > 0,
N1 = N - 1,
random(9, H),
!,
randomlist(N1,T).
/***************************************************************/
% Predicatul care initiaza calculul frecventei aparitiilor elementelor in cadrul listei:
% (i, o)
% Notand frecv(ITEML, FRL), semnificatia argumentelor este:
% ITEML - lista cu elementele ale caror frecventa dorim sa o calculam
% FRL - lista calculata de frecvente, de forma [f(numar1, frecventa_numar1), f(numar2, frecventa_numar2),…]
% Lista de frecvente ale unei liste vide este lista vida:
frecv([], []).
% Initiaza calculul frecventei de aparitii a primului element de lista, construind
% de la bun inceput primul element al listei de frecvente si facand unificarile corespunzatoare:
frecv([H|T], [f(H, N)|RESTLISTFRECV]) :-
frecvh(H, T, 1, N, LF, LF, RESTLISTFRECV).
/***************************************************************/
% Predicatul ajutator care efectueaza numararea propriu-zisa:
% (i, i, i, o, o, o, o)
% notand frecvh(ELEM, LISTA, APARITII_I, APARITII_TOTALE, ELEM_CURENT_LISTA_FILTRATA, LISTA_FILTRATA,
% REST_LISTA_FRECVENTE), semnificatia argumentelor este:
% ELEM - elementul ale carui aparitii le numaram la pasul curent
% LISTA - portiunea din lista de inspectat ramasa in care numaram aparitiile lui ELEM
% APARITII_I - numarul de aparitii de pana acum ale elementului ELEM
% APARITII_TOTALE - numarul total de aparitii ale elementului ELEM
% ELEM_CURENT_LISTA_FILTRATA - elementul curent al listei filtrate, care se va construi in pasul curent
% LISTA_FILTRATA - intreaga lista filtrata (care nu va mai contine aparitii ale lui ELEM)
% REST_LISTA_FRECVENTE - variabila care se va unifica cu restul listei de frecvente, dupa calculul frecventei lui ELEM
% Elementul curent este gasit in capul listei de inspectat. Incrementam nr. de aparitii, dar
% nu il trecem in lista filtrata:
frecvh(H, [H|T], N, NTOTAL, LFI, LF, RESTLISTFRECV) :-
N1 = N + 1,
!,
frecvh(H, T, N1, NTOTAL, LFI, LF, RESTLISTFRECV).
% Elementul curent nu este gasit in capul listei de inspectat. Nu incrementam nr. de aparitii, dar
% il trecem in lista filtrata:
frecvh(H, [Y|T], N, NTOTAL, [Y|RLFI], LF, RESTLISTFRECV) :-
H <> Y,
!,
frecvh(H, T, N, NTOTAL, RLFI, LF, RESTLISTFRECV).
% Am ajuns la capatul listei de inspectat si lista filtrata este vida.
% Deci am ajuns la finalul algoritmului, unificam numarul total de aparitii al elementului numarat cu numarul curent de aparitii,
% Unificam si restul listei de frecvente cu [], pentru a inchide lista
frecvh(_, [], N, N, [], [], []).
% Am ajuns la capatul listei de inspectat, insa lista filtrata nu este vida.
% Reluam prin initierea detectarii nr. de aparitii al capului listei filtrate (HLF) in restul (coada) listei filtrate, TLF.
% Initiem nr de aparitii cu 1, pentru lua in considerare si aparitia sa initiala din capul listei filtrate.
frecvh(_, [], N, N, [], [HLF|TLF], [f(HLF, NHLF)|REST]) :-
frecvh(HLF, TLF, 1, NHLF, LF, LF, REST).