Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программы классификации 49 9 Программа классифи...doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
944.13 Кб
Скачать

3.4.1. Описание списков в программе

Для указания Прологу того, что мы предполагаем использовать списки в программе, используется второй формат указания Domains:

mylist = elevent* ,

где mylist – объявление списка элементов, element – один из стандартных типов Турбо-Пролога, либо ранее описанный пользователем в Domains; “*” – обязательный элемент синтаксиса, обозначает список. Например, домен

namlist = integer*

объявляет список целых чисел. Таким образом, шапка программы для работы со списком:

Domains

namlist = integer *

Predicates

add( integer, namlist, namlist ) % Объявляем предикат добавления элемента в список

Clauses

/* Далее следуют клозы предиката add */

Рассмотрим некоторые предикаты для обработки списков.

3.4.2. Добавление элемента в список

Требуется запрограммировать предикат add (добавить). Он должен иметь три аргумента: добавляемый элемент X, исходный список L и L1 - результирующий список:

add ( X, L, L1).

Поскольку речь не идет о том, что элемент требуется поставить на некоторое определенное место, то наиболее простой способ добавить элемент в список – это вставить его в самое начало так, чтобы он стал новой головой. В этом случае предикат имеет самый простой вид, можно обойтись без рекурсии. Если X – это новый элемент, который добавляют в список L, то предикат добавления элемента в список запишется следующим образом:

add( X, L, [ X | L ] ).

Отношение add можно использовать в обратном направлении для того, чтобы удалить голову списка. Заметим, что особенность работы предикатов Пролога «в обе стороны» является широко эксплуатируемой и представляет приятную неожиданность в декларативном программировании. Как же Пролог узнает, что делать со списком: отсекать ему голову или, наоборот, добавлять? На это вопрос легко ответить, если вспомнить основной вычислительный механизм Пролога: сопоставление и унификация. Если, например, встретится цель

Goal add( 5, [ 3, 6, 1], L ),

в которой третий аргумент не конкретизирован, то согласно реализации предиката add будет выдан ответ:

L= [ 5, 3, 6, 1 ].

Если же будет задана цель, в которой первый и третий аргументы конкретизированы, а второй – нет, Пролог конкретизирует его опять таки согласно алгоритму добавления, но с точностью наоборот:

Goal add( 5, L, [ 5, 3, 6, 1 ] ).

L = [ 3, 6, 1 ].

Если первый аргумент нас не интересует, вместо него можно указать анонимную переменную, тогда цель будет выглядеть еще проще (с тем же результатом):

Goal add( _ , L, [ 5, 3, 6, 1 ] ).

3.4.3. Удаление элемента

Удаление элемента X из списка L можно определить в виде отношения

away( X, L, L1 ),

где L1 – это список L, из которого удален элемент X.

Поскольку заранее не известно, где находится в списке удаляемый элемент, без рекурсивного перебора списка не обойтись.

Определим отношение away с использованием рекурсии следующим образом: если X является головой списка, тогда результатом удаления будет хвост этого списка T (первое правило, без рекурсии). Иначе, если X не совпадает с головой списка, т.е. находится в хвосте списка, тогда его нужно оттуда удалить:

away( X, [ X | T ], T ).

away( X, [ Y | T], [ Y | T1 ] ):– away( X, T, T1 ).

Если в списке встречается несколько вхождений элемента X, то away сможет исключить их все при помощи возвратов. Вычисление по каждой альтернативе будет удалять лишь одно вхождение X, оставляя остальные в неприкосновенности. Например:

goal away ( 5, L, [ 5, 3, 5, 6, 1, 5 ],).

L = [ 3, 5, 6, 1, 5 ].

L = [ 5, 3, 6, 1, 5 ].

L = [ 5, 3, 5, 6, 1 ].

При попытке исключить элемент, не содержащийся в списке, отношение away неудачу.

Отношение away можно использовать в обратном порядке для того, чтобы добавлять элементы в список, вставляя их в произвольные места. Операция по внесению X в произвольное место некоторого списка Spisok, дающее в результате больший список Bolsh_spis, может быть определена предикатом add2:

add2( X, Spisok, Bolsh_spis ):-

away ( X, Bolsh_spis, Spisok).