Материал: Терёхин В. В. Turbo Prolog

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Эти утверждения содержат сведения об очках, набранных командами. Предположим, что необходимо сложить все очки и усреднить их. Сбор очков в список осуществляется при помощи встроенного предиката findall :

findall(Points,football(_,Points),Point_list)

Здесь Poits является свободной переменной для значений набранных командами очков, а Point_list - списочной переменной, элементы которой принадлежат к тому же домену, что и Points, в данном случае, к домену real.

Сама работа предиката скрыта от глаз пользователя. В нашем примере findall просматривает все утверждения с предикатом football, начиная с первого. Значение переменной Points (116), взятое из этого утверждения, присваивается голове списка Point_list. Остальные значения Points помещаются в список на последующие позиции. По завершению работы findall переменная Point_list принимает значение

[116.0,121.0,114.0,99.0,122.0]

Для подсчета среднего значения набранных очков применяется рекурсивное правило

sum_list([],0,0).

sum_list([H|T], Sum, Number) :- sum_list(T,Sum1,Number1), Sum = H + Sum1,

Number = Number1 + 1.

Оно напоминает правило sum из гл. 4.

Для получения суммы всех элементов списка Point_list это правило необходимо задать в качестве подцели

sum_list(Point_list,Sum,Number).

Сначала Турбо-Пролог сопоставляет эту подцель с вариантом правила sum_list([H|T],Sum,Number). Point_list при этом сопоставляется с [H|T], а пе-

ременные Sum и Number оказываются неопределенными. Рекурсии с первым вариантом правила продолжаются до тех пор, пока Point_list не превратиться в нулевой список; на каждой рекурсии очередной элемент списка помещается в стек. Теперь Турбо-Пролог пытается удовлетворить правило

sum_list([],0,0).

Переменным Sum и Number присваиваются нули, и таким образом правило полностью удовлетворено. Сворачивая рекурсию sum_list, ТурбоПролог последовательно, один за другим, извлекает из стека засланные туда элементы и складывает их с уже имеющимся значением суммы; при этом переменная Number каждый раз увеличивается на единицу. В итоге имеем следующие формы sum_list:

sum_list([122],122,1) sum_list([99,122],221,2) sum_list([114,99,122],335,3) sum_list([121,114,99,122],456,4) sum_list([116,121,114,99,122],572,5)

По окончанию рекурсий значениями переменных Sum и Number являются соответственно 572 и 5.

116

Совсем просто выглядит правило для нахождения среднего значения набранных очков:

Average = Sum / Number

Правило Average использует подсчитанное правилом Sum_list значения переменных Sum и Number. Результатом применения этого правила является присвоение переменной Average частного от деления Sum и Number, т. е.

114.4.

Программа "Очки" (листинг 5.7) демонстрирует использование предиката findall для сбора данных из базы данных в список.

____________________________________________________________

Листинг 5.7

/* Программа: Очки

*/

/* Назначение: Показ использования предиката

*/

/*

findall для вычисления среднего значения. */

domains

name = string points = real list = points *

predicates football(name,points)

sum_list(list,points,integer) report_average_football_score

goal

report_average_football_score.

clauses

/* факты (футбольная база данных) */ football("Ohio State",116.0). foot-ball("Michigan",121.0). football("Michigan State",114.0). football("Purdue",99.0). football("UCLA",122.0). report_average_football_score:-

findall(Points,football(_,Points),Point_list), sum_list(Point_list,Sum,Number), Average = Sum / Number,

write("College Football Power Rating:"), nl,

write(" Average Points = ",Average).

sum_list([],0,0).

sum_list([H|T], Sum, Number) :- sum_list(T,Sum1,Number1), Sum = H + Sum1,

117

Number = Number1 + 1.

/***** конец программы *****/

_____________________________________________________________

Программа подсчитывает сумму очков команд и их среднее значение. Внутренняя цель программы есть

report_average_football_score

Цель представляет собой правило, содержащее подцели findall, sum_list, Average, а также предикаты, осуществляющие вывод полученных результатов в нужной форме.

Начиная свою работу программа, пытается удовлетворить подцель findall в том виде, в котором она была описана. Когда подцель удовлетворена, делается попытка удовлетворить подцель sum_list, а затем Average. Переменной Average при этом присваивается значение 114.4, которое используется затем предикатом write. Теперь все подцели удовлетворены, следовательно, удовлетворена и цель программы.

*Упражнение

5.17.Возьмите текущею таблицу чемпионата СССР по футболу, введите в базу данных "Очки" результаты лучших десяти команд. Запустите программу на счет. Каким будет средний результат десятки ?

5.7. Заключение

В настоящей главе были представлены структура и функции списков в Турбо-Прологе, а также различные операции для работы с ними. Рассмотрение работы со списками началось с операций создания и печати списков при посредстве метода деления списка на голову и хвост. Завершилось это операциями поиска нужного элемента списка, деления, присоединения и сортировки списка. Затрагивался вопрос об использовании предиката findall для компоновки списка из данных базы данных.

Читая главу, вы познакомились с приемами создания правил, позволяющих описать цель программы. Вы научились превращать сформулированные на естественном языке запросы к программе в правила ТурбоПролога.

Рекомендуется читателю не пропускать предлагаемые упражнения, которые призваны углубить понимание основных структур и техники программирования. Упражнения помогают также научиться модифицировать демонстрационные программы с целью приспособить их к своим нуждам. Семь законченных программ данной главы показывают основные методы работы со списками и отличительные черты Турбо-Пролога. Их можно использовать в качестве заготовок для ваших собственных программ.

Чтение главы является обязательным, если вы собираетесь использовать списки в ваших программах, так как представленные здесь методы находят самое широкое применение при разработке программ на Турбо-

118

Прологе. Эти методы можно применять даже в том случае, если вы не понимаете до конца механизм их работы, хотя, конечно, понимание сделает Вам честь как программисту.

119