symbol) %В данном случае для всех предикатов тип - символьный
woman(symbol) %это может быть последовательность символов любой длины
parent(symbol, symbol)
father(symbol, symbol)
mother(symbol, symbol)
brother(symbol, symbol)
sister(symbol, symbol)
grandfather(symbol, symbol)
grandmother(symbol, symbol)
CLAUSES %Секция фактов и предложений
man("Sergey"). %В данной секции сначала записываем факты, такие как
man("Egor"). %Имена, принадлежащие мужчинам и женщинам,
man("Sergey_m").
man("Igor").
woman("Ludmila").
woman("Tatiana").
woman("Elena").
parent("Sergey", "Sergey_m").%Родственные отношения, первый параметр – Отец (Мать),
parent("Sergey", "Igor"). %Второй параметр – сын (дочь).
parent("Ludmila", "Sergey_m").
parent("Ludmila", "Igor").
parent("Sergey", "Elena").
parent("Ludmila", "Elena").
parent("Egor", "Sergey").
parent("Tatiana", "Sergey").
%Когда факты описаны, создаем правила вывода родственных отношений
%Отец, если он является родителем и мужчиной
father(X, Y):- parent(X, Y), man(X).
%Мать, если она является родителем и женщиной
mother(X, Y):- parent(X, Y), woman(X).
%Брат, если родитель для него является также родителем для X и X мужчина, имя Y не выводим
brother(X, Y):- parent(Z, X), parent(Z, Y), X<>Y, man(X).
%Сетсра, если родитель для неё является также родителем для X и X женщина, имя Y не выводим
sister(X, Y):- parent(Z, X), parent(Z, Y), X<>Y, woman(X).
%Дедушка, если он мужчина и является родителем для отца (матери) сына(дочери)
grandfather(X, Y):- man(X), parent(Z, Y), parent(X, Z).
%Баушка, если она женщина и является родителем для отца (матери) сына(дочери)
grandmother(X, Y):- woman(X), parent(Z, Y), parent(X, Z).
Теперь к программе можно обратиться с внешним запросом. На внешние запросы, в отличие от внутренних, находятся все возможные решения, поэтому поиск с возвратом не нужен.
Внешние запросы:
GOAL: mother(Name, “Sergey_m”)
Результат: Name = Ludmila
GOAL: grandfather(Name, “Igor”)
Результат: Name = Egor
Задание 2.
Написать программу, реализующую авиа-справочник. В справочнике содержится следующая информация о каждом рейсе: номер рейса, пункт назначения, цена билета. Реализовать вывод всей информации из справочника, поиск пункта назначения по номеру рейса. Реализовать поиск по пункту назначения с указанием максимально возможной цены билета (должны быть выведены все рейсы, цена билета на которые ниже указанного значения). Для удобства работы реализовать меню с соответствующими пунктами.
Решение:
Алгоритм меню: создаем после каждого поиска искусственную точку возврата, если пользователь не ввел цифру 4 (выход из программы), это позволяет после каждого поиска возвращаться к предикату описания меню.
После того как выбрано действия (цифра, соответствующая действию), происходит поиск нужного предиката, но т. к. запрос внутренний, то решение будет найдено только одно, чтобы найти все решения будет использоваться предикат fail, создающий искусственную точку возврата при любом исходе поиска решения.
PREDICATES %Описываем необходимые предикаты
sprav(integer, symbol, integer)
repeat
menu
action(integer)
CLAUSES %сначала заполняем секцию фактами – номер рейса, направление и цена.
repeat.
repeat:- repeat.
sprav(156, "Moskva", 12540).
sprav(457, "Omsk", 8560).
sprav(198, "Moskva", 19000).
sprav(235, "Novosibirsk", 4560).
sprav(897, "Vladivostok", 22590).
sprav(245, "Novosibirsk", 6870).
sprav(112, "Moskva", 10540).
sprav(145, "Moskva", 18790).
menu:- repeat, nl, %Выводим меню, 4 пункта
write("MENU:"), nl,
write("1 - spisok vsex reisov"), nl,
write("2 - naiti punkt naznachenia po nomeru reisa"), nl,
write("3 - naiti reisi po punktu naznachenia i cene"), nl,
write("4 - vixod iz programmi"), nl,
write("Vvedite nomer deistvia: "),
readint(Do), %Запрашиваем ввод с клавиатуры действия
action(Do). %Создаем действие
action(Type):- Type = 1, sprav(X, Y, Z), %Вывод информации о всех рейсах
Delimiter = "******************************",
write(Delimiter), nl,
write("REIS NOMER: ", X), nl,
write("V ", Y), nl,
write("CENA BILETA: ", Z, " rubley"),
nl, fail. %Искусственная точка возврата
action(Type):- Type = 2, %Вывод направления по номеру рейса
Delimiter = "------------------------------",
nl,
write("VVEDITE NOMER REISA: "),
readint(Nomer), nl, nl, %Ввод с клавиатуры номера рейса
sprav(Nomer, Y, Z), %Поиск в фактах номера рейса
write(Delimiter), nl, nl,
write("REIS NOMER: ", Nomer, " v ", Y),
nl, fail. %Искусственная точка возврата
action(Type):- Type = 3, %Вывод рейсов по направлению и предельной цене билета
Delimiter = "----------------------------------",
nl,
write("PUNKT NAZNACHENIA: "),
readln(Punkt), nl, %Ввод с клавиатуры направления
write("MAXIMALNAIA CENA : "),
readint(Cena), nl, nl, %Ввод с клавиатуры максимальной цены
sprav(X, Punkt, Y),
Y < Cena, %Одним из условием является цена за билет
%меньше максимальной введенной цены
write(Delimiter), nl, nl,
write("REIS NOMER: ", X),
nl, nl, fail. %Искусственная точка возврата
action(Type):- !, Type = 4. %Отсечение всех точек возврата если ввели цифру 4,
%при этом происходит выход из программы
GOAL
Menu %Запрос на вывод меню
Результат работы программы:
MENU:
1 - spisok vsex reisov
2 - naiti punkt naznachenia po nomeru reisa
3 - naiti reisi po punktu naznachenia i cene
4 - vixod iz programmi
Vvedite nomer deistvia: 2
VVEDITE NOMER REISA: 112
REIS NOMER 112 v Moskva
Задание 3.
Поменять порядок следования букв в слове на противоположный. Для разделения строки на символы использовать стандартный предикат frontchar (String, Char, StringRest), позволяющий разделять строку String на первый символ Char и остаток строки StringRest.
Решение:
Алгоритм работы: для изменения порядка следования букв используем списки. Список в пролог – это рекурсивная структура данных, состоящая из двух частей: голова и хвост. Сначала преобразуем строку в список, затем будем отделять голову от созданного списка и добавлять ее в хвост нового списка – получится реверс строки.
DOMAINS
arr = char* %Определяем список символьного типа
PREDICATES
getchar(symbol, arr) %Список до реверса
reverse(arr, arr, arr) %Список с обратным расположением букв
CLAUSES
getchar("", []):- !. %Если был последний элемент из строки, убираем точки %возврата
%Отделяем от строки первый символ и заносим его в голову списка, остаток строки в %хвост
getchar(Str, [H|T]):- frontchar(Str, H, E), getchar(E, T).
reverse([], L, L).
%Заносим голову в хвост, сдвигая каждый символ головы в хвост
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.