Управление перебором. Отсечение
Упражнение 5. Используя предикат maximum/3 (см. листинг 3.4), определите предикат maximum/4, вычисляющий максимальное из трех чисел.
Следующая программа посвящена решению квадратных уравнений с действительными коэффициентами в действительных числах. Коэффициенты уравнения вводятся пользователем с клавиатуры. Решением является список корней уравнения. В предикат solution, который находит решение уравнения по его коэффициентам, добавлен еще один аргумент — метка. С помощью метки определяется предикат print, который печатает результат.
class predicates
solution: (real A, real B, real C, real* [out], integer Mark [out]).
roots: (real A, real B, real D, real* Решение [out]).
print: (integer, real* Решение).
clauses
solution(0, 0, 0, [], -1):- !.
solution(0, 0, _, [], 0):- !.
solution(0, B, C, [-C/B], 1):- !.
solution(A, B, C, L, 2):-
roots(A, B, B^2 - 4 * A * C, L).
roots(A, B, 0, [-B/(2 * A)]):- !.
roots(_, _, D, []):- D < 0, !.
roots(A, B, D, [(-B + Q)/(2 * A), (-B - Q)/(2 * A)]):-
Q = math::sqrt(D * 1).
print(-1, _):- !, write("Решение - любое число").
print(0, _):- !, write("Уравнение линейное, решений нет.").
print(1, [X]):- !, write("X = ", X).
print(2, [X]):- !, write("X1 = X2 = ", X).
print(2, [X1, X2]):- !, write("X1 = ", X1, ", X2 = ", X2).
print(_, _):- write("Решений нет.").
run():-
write("Введите коэффициенты уравнения "
"A*X^2 + B*X + C = 0\nA = "),
A = read(), clearInput(),
write("B = "),
B = read(), clearInput(),
write("C = "),
C = read(), clearInput(),
solution(A, B, C, L, Mark),
print(Mark, L),
_ = readLine().
Пример
3.5.
Решение квадратных уравнений в действительных числах
Предикат read считывает терм любого домена. При этом буфер ввода полностью не очищается, для этого вызывается предикат clearInput. Предикат sqrt/1 возвращает квадратный корень из неотрицательного числа (ureal). Умножение дискриминанта на единицу в выражении Q = math::sqrt(D * 1) используется для преобразования типа: значение переменной D принадлежит домену real, а значение аргумента предиката sqrt должно принадлежать домену math::ureal. Выполнение операции умножения на единицу вынуждает компилятор искать нужный тип для результата.
Для преобразования типов предназначены предикаты сonvert и tryConvert. Первый из них всегда успешен. Если преобразование невозможно, то возбуждается исключение. Второй предикат детерминированный. В случае невозможности преобразоваия он принимает значение ложь.
Можно заменить строку Q = math::sqrt(D * 1) в программе парой строк:
D1 = convert(math::ureal, D), Q = math::sqrt(D1).
Упражнение 6. Напишите программу, которая решает линейные уравнения. Коэффициенты вводятся пользователем с клавиатуры.
В программе, приведенной ниже, генерируются все двузначные числа. Кроме этого, с помощью конструкции […||…] четные двузначные числа собираются в список.
class facts
digit: (integer).
class predicates
twoDigitNumber: (integer) nondeterm (o).
clauses
digit(0). digit(1). digit(2). digit(3). digit(4).
digit(5). digit(6). digit(7). digit(8). digit(9).
twoDigitNumber(10 * A + B):-
digit(A),
A > 0,
digit(B).
run():-
twoDigitNumber(X),
write(X), nl,
fail;
write("Список четных двузначных чисел:\n"),
L = [10 * A + B || digit(A), A > 0, digit(B), B mod 2 = 0],
write(L),
_ = readLine().
Пример
3.6.
Генератор двузначных чисел
Упражнение 7.
- Определите, не запуская программу, в каком порядке будут генерироваться двузначные числа (см. листинг 3.6).
- Определите предикат, который генерирует целые числа, делящиеся на 3 без остатка, в пределах от 0 до 100.
Упражнения
-
Как-то раз сестры Маша, Даша и Глаша испекли пирог. Одна из них месила тесто, другая готовила начинку, а третья выпекала пирог в духовке. Известно, что каждое из следующих высказываний истинно:
- если Глаша месила тесто, то Даша готовила начинку;
- если Маша выпекала пирог, то месила тесто Даша;
- если Глаша готовила начинку, то Маша выпекала пирог;
- если Даша месила тесто, то Маша готовила начинку;
- если Глаша выпекала пирог, то Маша месила тесто.
Кто из сестер месил тесто, кто готовил начинку, а кто выпекал пирог?
-
Жители острова A, B и С, один из которых всегда говорил правду, другой всегда лгал, а третий был хитрецом — иногда говорил правду, а иногда лгал, сообщили о себе следующее:
- A: "Я хитрец";
- B: "Да, A хитрец";
- C: "Я не хитрец".
Определите, кто из них кем был на самом деле.
-
Определите предикаты, результатом действия которых является упорядочивание пары чисел или тройки чисел:
упорядочение(X, Y, Min, Max); упорядочение(X, Y, Z, Min, Ave, Max).
- Определите число полных лет человека на текущий день по его дате рождения.
- Вычислите количество полных месяцев, оставшихся до дня рождения человека, по его дате рождения.
- Сгенерируйте все палиндромы длиной пять, состоящие из 0 и 1.
- Сгенерируйте с помощью конструкции […||…] список всех белых и список всех черных клеток шахматной доски (индексы полей принимают значения от 1 до 8).
-
Определите в программе для шахматной доски
ход:- коня;
- ладьи;
- слона;
- ферзя;
- короля.