Списки. Предикаты высших порядков
7.5. Предикаты сортировки списка
Операцию сортировки списка выполняют предикаты sort и sortBy класса list. Сортировка выполняется в соответствии с алгоритмом слияния. По умолчанию список сортируется по возрастанию элементов:
L = sort([3, 6, 5, 1, 7, 8]).
Для упорядочения списка по убыванию элементов используется предикат sort/2:
L = sort([3, 6, 5, 1, 7, 8], descending()).
Предикат sortBy выполняет сортировку в соответствии с заданным критерием. Например, при вызове
L = sortBy({(X, Y) = compare(X mod 3, Y mod 3)}, [3, 5, 7, 6, 1])
элементы списка будут упорядочены по возрастанию в соответствии со значением их остатка от деления на 3.
Критерий сортировки можно определить как в виде анонимного предиката (см. выше), так и в виде отдельного предиката (см. листинг 7.8).
class predicates comp : comparator{tuple{string, integer}}. clauses comp(tuple(X, N), tuple(Y, N)) = compare(X, Y):- !. comp(tuple(_, N), tuple(_, K)) = compare(N, K). run():- write(list::sortBy(comp, [tuple("Маша", 18), tuple("Даша", 19), tuple("Глаша", 18), tuple("Паша", 17)])), _ = readLine().Пример 7.8. Сортировка по заданному критерию
Список содержит сведения об именах и возрасте группы студентов. В результате применения предиката sortBy список упорядочивается по возрасту, а если возраст одинаковый, то по именам, в соответствии с лексикографическим порядком.
В следующей программе приведены примеры использования предикатов второго порядка класса list — forAll/2, fold/3, removeDuplicatesBy/2, maximumBy/2 и decompose/2.
open core, console, list class predicates comp : comparator{tuple{string, integer}}. clauses comp(tuple(_, N), tuple(_, K)) = compare(N, K). % по возрасту run():- L = [tuple("Маша", 18), tuple("Даша", 19), tuple("Глаша", 18), tuple("Паша", 17)], % вывод элементов списка forAll(L, {(tuple(X, N)):- write(X, " - ", N), nl}), nl, % суммарный возраст студентов write(fold(L, {(tuple(_, K), S) = K + S}, 0)), nl, % удаление студентов того же возраста, остаются по одному write(removeDuplicatesBy(comp, L)), nl, % самый старший по возрасту студент write(maximumBy(comp, L)), nl, % разбиение на группы по возрасту write(decompose(L, {(tuple(_, Age)) = Age})), _ = readLine().Пример 7.9. Предикаты высших порядков
Упражнения
- По заданному списку проверьте, образуют ли его элементы арифметическую прогрессию.
- Определите операцию возвращения из списка слов всех слов-палиндромов. Для разбиения слов на списки символов используйте предикат string::toCharList/1.
- Определите операцию симметрической разности множеств, представленных списками.
-
Определите операцию циклического сдвига элементов списка на заданное количество элементов
- вправо;
- влево.
- Сгенерируйте все перестановки списка, содержащие заданный подсписок.
- Сенерируйте все перестановки с повторениями, состоящие из заданного числа элементов, для данного множества элементов.
- Для заданного множества сгенерируйте сочетания с повторениями, состоящие из заданного числа элементов.
- Определите критерий сортировки элементов списка, состоящего из троек вида tuple(X, Y, Z), в которых хранятся имена (X), отчества (Y) и фамилии (Z) людей. Список должен быть упорядочен по фамилиям, при одинаковых фамилиях — по именам, при одинаковых именах и фамилиях — по отчествам.
- Найдите разбиение на классы эквивалентности множества элементов неотрицательных целых чисел. Два элементы эквивалентны, если они имеют одинаковые остатки при делении на n.