Управление перебором. Отсечение
Упражнение 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).
-
Определите в программе для шахматной доски
ход:
- коня;
- ладьи;
- слона;
- ферзя;
- короля.