Опубликован: 12.02.2014 | Уровень: для всех | Доступ: платный
Лекция 3:

Управление перебором. Отсечение

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >

Упражнение 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.

  1. Определите, не запуская программу, в каком порядке будут генерироваться двузначные числа (см. листинг 3.6).
  2. Определите предикат, который генерирует целые числа, делящиеся на 3 без остатка, в пределах от 0 до 100.

Упражнения

  1. Как-то раз сестры Маша, Даша и Глаша испекли пирог. Одна из них месила тесто, другая готовила начинку, а третья выпекала пирог в духовке. Известно, что каждое из следующих высказываний истинно:

    1. если Глаша месила тесто, то Даша готовила начинку;
    2. если Маша выпекала пирог, то месила тесто Даша;
    3. если Глаша готовила начинку, то Маша выпекала пирог;
    4. если Даша месила тесто, то Маша готовила начинку;
    5. если Глаша выпекала пирог, то Маша месила тесто.

    Кто из сестер месил тесто, кто готовил начинку, а кто выпекал пирог?

  2. Жители острова A, B и С, один из которых всегда говорил правду, другой всегда лгал, а третий был хитрецом — иногда говорил правду, а иногда лгал, сообщили о себе следующее:

    1. A: "Я хитрец";
    2. B: "Да, A хитрец";
    3. C: "Я не хитрец".

    Определите, кто из них кем был на самом деле.

  3. Определите предикаты, результатом действия которых является упорядочивание пары чисел или тройки чисел:

    упорядочение(X, Y, Min, Max);
    упорядочение(X, Y, Z, Min, Ave, Max).
    
  4. Определите число полных лет человека на текущий день по его дате рождения.
  5. Вычислите количество полных месяцев, оставшихся до дня рождения человека, по его дате рождения.
  6. Сгенерируйте все палиндромы длиной пять, состоящие из 0 и 1.
  7. Сгенерируйте с помощью конструкции […||…] список всех белых и список всех черных клеток шахматной доски (индексы полей принимают значения от 1 до 8).
  8. Определите в программе для шахматной доски 8\times 8 ход:

    • коня;
    • ладьи;
    • слона;
    • ферзя;
    • короля.
< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.

Айдана Ахметова
Айдана Ахметова
Россия
Дмитрий Куянов
Дмитрий Куянов
Россия, Омск, ОмГТУ