densal03
densal03

Reputation: 33

second largest from a list prolog

i'm writing a function that returns true if E is the second largest element from the list, especially trying to use the library https://www.swi-prolog.org/pldoc/man?section=lists

like this:

secLarg([], E).
secLarg([_], E).
secLarg([T], E) :- L is max_member(T, E), delete(T, L), max_member(E, L).

so using some sort of composition of library functions max_member and delete, however this solution is not working, as max_member appears to return only true/false, not what the specific largest element is. do you have any idea about how could I find if E is the second largest element by any way using these functions?

Upvotes: 1

Views: 283

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476614

The problem is that L is max_member(T, E) does not make much sense. A predicate does not return a value: it either succeeds or fails. It uses unification to unify a variable with the result.

If you use [T] to unify with, you will only unify with lists with exactly one element. Whereas you probably want to unify with lists with an arbitrary number of elements.

delete/3 also does not alter the list, it produces a new list where it removed the largest member:

secLarg(Xs, E) :-
    max_member(Lg, Xs),
    delete(Xs, Lg, Xs1),
    max_member(E, Xs1).

It also does not make much sense to write secLarg([], E) and secLarg([_], E), since for such lists, there is no second largest:

% secLarg([], E).
% secLarg([_], E).
secLarg(Xs, E) :-
    max_member(Lg, Xs),
    delete(Xs, Lg, Xs1),
    max_member(E, Xs1).

Beware that delete/3 will delete all elements with the given value. Indeed:

?- delete([1,4,2,5,4], 4, R).
R = [1, 2, 5].

So if there is a list where the largest value occurs multiple times, it will not select the largest value (which is also the second largest one).

Upvotes: 2

Related Questions