Zoran
Zoran

Reputation: 459

prolog: sorting w.r.t. some attribute

My database is similar to this:

% happy(Person,Happiness)
happy(1,10).
happy(2,5).
happy(3,8).
happy(4,1).

I want to sort people w.r.t. their happiness.

I coded the following and it does what I want. However it looked cumbersome to me. Any improvements?

? - sortPeople(Ts).
Ts = [1, 3, 2, 4].

My solution:

getFirst([],R,R).
getFirst([[H1,_]|T],F,R) :-
    append([H1],F,R1),
    getFirst(T,R1,R).

compareHappiness(X, [_,S1], [_,S2]) :- compare(X, S1, S2).

sortPeople(Ts) :-
    findall([X,Y], happy(X,Y), List), 
    predsort(compareHappiness, List, SortedList),
    getFirst(SortedList,[],Ts).

Upvotes: 0

Views: 314

Answers (2)

ssbarbee
ssbarbee

Reputation: 1712

-Here is what I got :

sort(Rez) :- findall([Happiness,PId],happy(PId,Happiness),List),
             msort(List,LSorted),
             findall(PersonID,member([_,PersonID],LSorted),Sorted),
             reverse(Sorted,Rez).

Upvotes: 1

mat
mat

Reputation: 40778

Consider using more descriptive and declarative predicate names, for example:

person_happiness(1, 10).
person_happiness(2, 5).
person_happiness(3, 8).
person_happiness(4, 1).

To sort people by happiness, consider using the built-in keysort/2, which is more efficient than predsort/3. You only need to build key-value pairs, for which by convention the functor -/2 is used, and instead of your auxiliary predicate, consider using the SWI-Prolog built-ins pairs_values/2 and reverse/2:

descending_happiness(Ps) :-
        findall(H-P, person_happiness(P, H), HPs),
        keysort(HPs, HPs1),
        pairs_values(HPs1, Ps1),
        reverse(Ps1, Ps).

Example query:

?- descending_happiness(Ps).
Ps = [1, 3, 2, 4].

Upvotes: 2

Related Questions