второй по величине из пролога списка

#list #prolog #max

#Список #пролог #макс

Вопрос:

я пишу функцию, которая возвращает true, если E является вторым по величине элементом из списка, особенно при попытке использовать библиотеку https://www.swi-prolog.org/pldoc/man?section=lists

вот так:

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

таким образом, используя какую-то композицию библиотечных функций max_member и delete, однако это решение не работает, поскольку max_member, по-видимому, возвращает только true / false, а не какой конкретный наибольший элемент. есть ли у вас какие-либо идеи о том, как я мог бы найти, является ли E вторым по величине элементом каким-либо образом, используя эти функции?

Ответ №1:

Проблема в том, что L is max_member(T, E) это не имеет особого смысла. Предикат не возвращает значение: он либо завершается успешно, либо завершается неудачно. Он использует унификацию для унификации переменной с результатом.

Если вы используете [T] для объединения с, вы будете объединять только со списками, содержащими ровно один элемент. В то время как вы, вероятно, хотите унифицировать списки с произвольным количеством элементов.

delete/3 также не изменяет список, он создает новый список, в котором он удалил самый большой элемент:

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

Также не имеет особого смысла писать secLarg([], E) и secLarg([_], E) , поскольку для таких списков нет второго по величине:

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

Будьте осторожны, это delete/3 приведет к удалению всех элементов с заданным значением. Действительно:

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

Поэтому, если есть список, в котором наибольшее значение встречается несколько раз, он не будет выбирать наибольшее значение (которое также является вторым по величине).