- •Оглавление
- •Логическое программирование. Язык Prolog.
- •1. Предикаты Пример 1.1. Максимум из двух чисел
- •Пример 5.2. Вычисление факториала
- •6. Хвостовая рекурсия Пример 6.1. Вычиление факториала с с использованием хвостовой рекурсии
- •Пример 6.2. Вычисление чисел Фибоначчи
- •7. Обработка списков Пример 7.1. Вычисление длины списка
- •Пример 7.2. Проверка принадлежности элемента списку
- •Пример 7.3. Соединение двух списков
- •Пример 7.4. Обращение списка
- •Пример 7.5. Среднее арифметическое элементов списка.
- •8. Сортировка списков Пример 8.1. Пузырьковая сортировка
- •Пример 8.2. Сортировка вставкой
- •Пример 8.3. Сортировка выбором
- •9. Строки
- •Пример 9.3. Преобразование строки в список символов
- •Пример 9.4. Подсчет кол-ва вхождений заданного символа в строку
- •Пример 9.6. Замена заданного символа в строке – на другой
- •Пример 9.7. Удаление части строки
- •Пример 9.8. Копирование части строки
- •Пример 9.9. Вставка одной строки внутрь другой
- •10. Множества Пример 10.1. Превращение произвольного списка в множество
- •Пример 10.2. Операция объединения двух множеств.
- •Пример 10.3. Пересечение множеств
- •Пример 10.4. Разность множеств
- •Пример 10.5. Проверка, является ли одно множество подмножеством другого.
- •Пример 10.6. Предикат, реализующий отношение равенства двух множеств.
- •Пример 10.7. Определение собственного подмножества множества
- •Пример 10.8. Симметричная разность
- •Пример 10.9. Дополнение множества
- •11. Деревья Пример 11.1. Принадлежность элемента дереву
- •Пример 11.2. Замена заданного значения на другое в дереве
- •Пример 11.3. Подсчет общего количества вершин дерева
- •Пример 11.4. Подсчет количества листьев (узлов без сыновей)
- •Пример 11.5. Подсчет суммы чисел в вершинах дерева
- •Пример 11.6. Предикат, вычисляющий высоту дерева
- •Пример 11.7. Проверка принадлежности значения двоичному справочнику .
- •Пример 11.8. Добавление элемента в двоичный справочник
- •Пример 11.9. Генератор случайного двоичного справочника из чисел
- •Пример 11.10. Удаление заданного значения из двоичного справочника
- •Пример 11.11. Преобразование произвольного списка в двоичный справочник
- •Пример 11.12. Предикат, сворачивающий заданный двоичный справочник в список
- •12. Базы знаний Пример 12.1. Вычисление чисел Фибоначчи с запоминанием результатов
- •13. Логические задачи (головоломки) Пример 13.1. Перестановка кубиков
- •Пример 13.2. Ханойский башни
- •Пример 13.3. Волк, коза и капуста
- •Пример 13.4. Побег из Зурга
Пример 11.7. Проверка принадлежности значения двоичному справочнику .
В
двоичном справочнике
если искомое значение не совпадает с
тем, которое хранится в корне
, то его имеет смысл искать только в
левом поддереве, если оно меньше
корневого, и, соответственно, только в
правом поддереве, если оно больше
корневого значения.
/* X – корень дерева */
ordtree_member(X,tr(X,_,_)):-!.
/* X - принадлежит левому поддереву */
ordtree_member(X,tr(K,L,_)):-
X<K,!,
ordtree_member(X,L).
/* X - принадлежит правому поддереву */
ordtree_member(X,tr(K,_,R)):-
X>K,!,
ordtree_member(X,R).
?- ordtree_member(8, tr(5, tr(3,nil, nil), tr(8, tr(6,nil,nil), tr(9,nil,nil)))).
Yes
Пример 11.8. Добавление элемента в двоичный справочник
Предикат будет иметь три аргумента. Первым аргументом будет добавляемое значение, вторым - дерево , в которое нужно добавить данное значение, третьим - результат вставки первого аргумента во второй.
Рекурсия будет основана на двух базисах и двух правилах. Первый базис: если вставлять любое значение в пустое дерево , то в результате получим дерево , у которого левое и правое поддеревья - пустые, в корне записано добавляемое значение. Второй базис: если вставляемое значение совпадает со значением, находящимся в корневой вершине исходного дерева , то результат не будет отличаться от исходного дерева (в двоичном справочнике все элементы различны). Два правила рекурсии определяют, как нужно действовать, если исходное дерево непустое и его корневое значение отличается от вставляемого значения. В этой ситуации, если добавляемое значение меньше корневого, то его нужно добавить в левое поддерево, иначе - искать ему место в правом поддереве.
/* вставка в пустое дерево: вставляем в корень */
tree_insert(X, nil, tr(X,nil,nil)).
/* вставляем X в пустое дерево, получаем дерево с X в корневой вершине,
пустыми левым и правым поддеревьями */
tree_insert(X,tr(X,L,R),tr(X,L,R)):- !.
/* вставляем X в дерево со значением X в корневой вершине,
оставляем исходное дерево без изменений */
tree_insert(X,tr(K,L,R),tr(K,L1,R)):-
X<K,!,
tree_insert(X,L,L1).
/* вставляем X в дерево с большим X элементом в корневой вершине,
значит, нужно вставить X в левое поддерево исходногодерева */
tree_insert(X,tr(K,L,R),tr(K,L,R1)):-
tree_insert(X,R,R1).
/* вставляем X в дерево с меньшим X элементом в корневой вершине, значит,
нужно вставить X в правое поддерево исходного дерева */
?- tree_insert(13, tr(5, tr(3,nil, nil), tr(8, tr(6,nil,nil), tr(9,nil,nil))), T).
T = tr(5, tr(3, nil, nil), tr(8, tr(6, nil, nil), tr(9, nil, tr(13, nil, nil)))) ;
Пример 11.9. Генератор случайного двоичного справочника из чисел
Предикат будет иметь два аргумента. Первый, входной, будет задавать требуемое количество элементов. Второй, выходной, будет равен сгенерированному дереву .
Рекурсия будет по количеству вершин дерева . Базис рекурсии: нулевое количество вершин имеется только в пустом дереве . Если количество вершин должно быть больше нуля, то нужно (с помощью встроенного предиката random, рассмотренного в пятой лекции) сгенерировать случайное значение, построить дерево , имеющее вершин на одну меньше, чем итоговое дерево , вставить случайное значение в построенное дерево , воспользовавшись созданным перед этим предикатом tree_insert.
/* ноль вершин соответствует пустому дереву */
tree_gen(0, nil):- !.
tree_gen(N,T):-
X is random(100), /* X - случайное число из промежутка [0,100] */
N1 is N-1, /* уменьшаем счетчик кол-ва вершин */
tree_gen(N1,T1), /* T1 - дерево, имеющее N-1 вершин */
tree_insert(X, T1, T). /* вставляем X в дерево T1 */
?- tree_gen(6, T).
T = tr(98, tr(8, nil, tr(60, nil, tr(84, tr(68, nil, tr(70, nil, nil)), nil))), nil) ;
