Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LP_5(Списки)).doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
201.73 Кб
Скачать

7.2.2.3 Получение списка по условию

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

Например, из списка [1,12,3,14,5,8], выберем лишь элементы большие чем 6.

Нам надо реализовать три предложения.

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

2. если нет - мы должны отказаться от элемента.

3. если список пуст, мы возвратим пустой список.

Реализация первого предложения (Р1) будет таким:

решето([X| Tail],[X|Result]):-

X > 6, % is X greater than 6 ?

решето(Tail,Result). % if so then go find the rest

Второе правило (Р2) - отказ от ненужного элемента списка запишется так:

решето([ThrowAway|Tail],Result):- % выбрасываем голову и

решето(Tail,Result). % рассматриваем хвост

Последнее предложение должно выглядеть, например, так:

решето([],[]).

Проверка

?- решето([1,12,3,14,5,8], Result).

Result = [12, 14, 8]

Теперь посмотрим, как работает программа на таком запросе

? - решето([1,12,3,14,5,8], Result).

Получается, что все начинается со второго предложения.

Здесь подцель 1>6 явно терпит неудачу, так что мы переходим к третьему предложению и пробуем выражения решето([1,12,3,14,5,8], Result) в таком виде: решето([1|12,3,14,5,8],Result), что означает вызов уже в виде:решето([12,3,14,5,8],Result), а это соответствует второму предложению.

Теперь подцель 12>6 успешна, и мы делаем запрос цели решето([3,14,5,8],Result). Но, обратите внимание, что в этом предложении происходит засылка «успешного» числа 12 в результирующий список.

Шагая далее через наш пример, мы видим, пока наконец мы не добираемся до цели, во втором предложении успешными будут также 14 и 8. А по исчерпанию списка выполнится первое предложение, что даст унификацию Result с [].

Теперь, выходя из рекурсии, мы будем благодаря второму предложению получать список в обратном порядке: сначала [8], затем [14,8], и наконец [12,14,8], прежде, чем получим успешный ответ.

Но правильный ответ будет таким:

Result = [12, 14, 8] ;

Result = [12, 14] ;

Result = [12, 8] ;

Result = [12] ;

Result = [14, 8] ;

Result = [14] ;

Result = [8] ;

Result = [].

(Здесь, как всегда для нового запроса – нажимаем Enter)

Если нам нужен один, но самый полный ответ, то первое предложение (Р1) нужно

записать так:

решето([X| Tail],[X|Result]):-

X > 6, !, % Поставлен “восклицательный знак”

решето(Tail,Result). % if so then go find the rest

Теперь результат будет кратким и полным:

?- решето([1,12,3,14,5,8], Result).

Result = [12, 14, 8].

?-

Никаких других решений не выдаётся.

То, что было использовано в написании, является предикатом cut (англ. отсечение), но пишется как восклицательный знак. Его назначение – ограничить пространство поиска решений, и тем самым повысить эффективность процедур, реализующих программы на прологе.

Его применение изменяет декларативную логику программы и поэтому, может привести к неправильным решениям. Если это случается, то такое отсечение называется «красным», в отличие от «зелёного» отсечения (как в нашем случае). У нас получается только одно, НО правильное решение.

Вывод. Применение отсечений требуем тщательной проверки

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]