Search code examples
listprologclpfd

Prolog Sorting a List of Structure, arithmetic error


I've been trying to sort a list of structure.

The structure is like this

% person(Name, Weight).
person(tom, 65).
person(dan, 70).
person(mike, 80).

And the list would be like this

List = [person(tom, 65), person(dan, 70), person(mike, 80)].

I want to sort the list from greatest weight to least. Like this:

SortList = [person(mike, 80), person(dan, 70), person(tom, 65)].

So far I have this:

sortListPerson([], []).
sortListPerson([person(NameP, WP)|Rest], Result):-
     sortListPerson(Rest, List),
     insertPerson(person(NameP, WP), List, Result).

insertPerson(person(NameP, WP), [], [person(NameP, WP)]).
insertPerson(person(NameP1, WP1), [person(NameP2, WP2)|Rest],   [person(NameP1, WP1)|List]):-
    integer(WP1),
    integer(WP2),
    WP1 @>= WP2,
    insertPerson(person(NameP2, WP2), Rest, List).
insertPerson(person(NameP1, WP1), [person(NameP2, WP2)|Rest], [person(NameP2, WP2)|List]):-
    integer(WP1),
    integer(WP2),
    WP1 @< WP2,
    insertInPlace(person(NameP1, WP1), Rest, List).

I've tried with a list of two persons and it works:

?- sortListPerson([person(a, 10), person(b, 30)], SortList).

SortList = [person(b,30),person(a,10)] ? ;

But when I try with a list of 3 or more person appears an error:

?- sortListPerson([person(a, 10), person(b, 30), person(c, 40)], SortList).
{ERROR: arithmetic:>=/2 - expected an arithmetically evaluable expression, found person(a,10)}

no
?- 

Can anybody help?


Solution

  • The way I see it your insertion-sort is okay, except for the second clause of insertPerson/3:

    :- use_module(library(clpfd)).
    
    insertPerson(person(N,W), [], [person(N,W)]).
    insertPerson(person(N1,W1), [person(N2,W2)|Ps], [person(N1,W1),person(N2,W2)|Ps]) :-
       W1 #>= W2.                                   % If Ps is in order, we're done!
    insertPerson(person(N1,W1), [person(N2,W2)|Ps], [person(N2,W2)|Qs]) :-
       W1 #< W2,
       insertPerson(person(N1,W1), Ps, Qs).
    

    Sample query:

    ?- sortListPerson([person(tom,65),person(dan,70),person(mike,80)], Xs).
    Xs = [person(mike,80),person(dan,70),person(tom,65)] ;
    false.