- •Оглавление
- •Логическое программирование. Язык Prolog.
- •1. Предикаты Пример 1.1. Максимум из двух чисел
- •Пример 5.2. Вычисление факториала
- •6. Хвостовая рекурсия Пример 6.1. Вычиление факториала с с использованием хвостовой рекурсии
- •Пример 6.2. Вычисление чисел Фибоначчи
- •Пример 7.4. Обращение списка
- •Пример 7.5. Среднее арифметическое элементов списка.
- •7. Обработка списков Пример 7.1. Вычисление длины списка
- •Пример 7.2. Проверка принадлежности элемента списку
- •Пример 7.3. Соединение двух списков
- •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. Побег из Зурга
13. Логические задачи (головоломки) Пример 13.1. Перестановка кубиков
Задача состоит в выработке плана переупорядочивания кубиков, поставленных друг на друга, как показано на рисунке. На каждом шагу разрешается переставлять только один кубик. Кубик можно взять только тогда, когда его верхняя поверхность свободна. Кубик можно поставить либо на стол, либо на другой кубик. Для того, чтобы построить требуемый план, мы должны отыскать последовательность ходов, реализующую заданную трансформацию.
% удаление элемента Х из списка, результат - в L
del(X, [X | L], L).
del(X, [Y | L], [Y | L1]):- del(X, L, L1).
% состояние: s(X, Y) где X - предыдущий шаг, Y - последующий допусимый шаг
% Перенести верхний кубик Top1 на столбик Stack2
s( Stacks, [Stackl, [Top1 | Stack2] | OtherStacks] ) :-
del([Top1 | Stackl], Stacks, Stacksl), % Найти первый столбик
del(Stack2, Stacksl, OtherStacks). % Найти второй столбик
goal(Situation):-
member([a,b,c], Situation). % Целевое состояние:
% Вызов поиска:
% solve([[c,a,b], [], []], Solution). % Начальное сотояние
/*
solve(N, [N]):- goal(N).
solve(N, [N | Sol1]):-
s(N, N1),
solve(N1, Sol1).
% solve(Node, Solution):
% Решение Solution представляет собой ациклический путь (узлы в
% котором указаны в обратном порядке) между узлом Node и целью
solve(Node, Solution) :-
depthfirst( [], Node, Solution).
% depthfirst( Path, Node, Solution):
% решение Solution формируется в результате продления пути
% [Node | Path] до целевого узла
depthfirst( Path, Node, [Node | Path] ) :-
goal( Node).
depthfirst( Path, Node, Sol) :-
s( Node, Node1),
not member( Node1, Path), % Предотвращение цикла
depthfirst( [Node | Path], Node1, Sol).
*/
solve( Start, Solution) :- breadthfirst( [ [Start] | Z] - Z, Solution).
breadthfirst( [ [Node | Path] | _] - _, [Node | Path] ) :- goal( Node).
breadthfirst( [Path | Paths] - Z, Solution) :-
extend( Path, NewPaths),
conc( NewPaths, Z1, Z), % Добавить NewPaths в конец
Paths \== Z1, % Множество возможных путей – не пустое
breadthfirst( Paths - Z1, Solution).
Пример 13.2. Ханойский башни
Имеется 3 стержня и N дисков разного диаметра, насаженные последовательно на 1 из стержней. Требуется переместить диски с одного стержня на другой, используя один стержень как вспомогательный.
Правила перемещения дисков:
разрешается снимать со стержня только верхний диск,
запрещается класть больший диск на меньший,
при каждом ходе передвигается только один диск.
% move(число_дисков, откуда, куда, через)
move(1,X,Y,_) :-
write('Перемещаем диск с '),
write(X), write(' стержня на '),
write(Y), nl.
move(N,X,Y,Z) :-
N>1,
M is N-1,
move(M,X,Z,Y),
move(1,X,Y,_),
move(M,Z,Y,X).
% Предикат для запуска поиска решений задачи размерности X
hanoi(X):- move(X, 'лев.', 'прав.', 'центр.').
% Запуск поиска решения:
% ?- hanoi(4).
