Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПРОЛОГ.doc
Скачиваний:
3
Добавлен:
21.11.2019
Размер:
311.81 Кб
Скачать

3.6.2. Разделение списков на голову и хвост

Основным приемом работы со списками является представление списков в виде «Головы» (Head) и «Хвоста» (Tail). Для иллюстрации напишем правило для предиката p2 из предыдущего раздела:

clauses

p2([]).

p2([l(I,S)|T]):-

write(I," ",S),nl,

p2(T).

Поиск элемента в списке:

search(H,[H,_]).

search(H,[_,T]):-search(H,T).

Получить сумму числовых элементов списка можно очевидным способом:

sumList([],S).

sumList([H|T],S):-S1=S+H,sumList(T,S1).

А для иллюстрации работы со стеком применим «неочевидный» прием:

predicates

sumlist(integer*,integer)

goal

L=[1,2,3,4],

sumlist(L,S),

write(S) .

clauses

sumlist([],0).

sumlist([H|T],X):-sumlist(T,S),X = S+H.

До тех пор, пока не удовлетворено первое правило, Пролог будет очищать список, сбрасывая «головы» в стек. Затем он присвоит 0 свободной переменной. А далее будет суммировать элементы стека, присваявая значения промежуточной суммы переменной X и возвращать элементы стека в список. (По моему мнению, если уж вы выбрали Пролог, не стоит жертвовать логической ясностью ради «оптимизации»)

Встроенный предикат findall

findall собирает компоненты факта в список.

domains

фам_им_от=ф(symbol,symbol,symbol)

лист_фам_им_от=фам_им_от*

facts - f1

гриб(symbol)

язык_программирования(integer,symbol)

фио(фам_им_от)

predicates

собрать_фио(лист_фам_им_от)

................

goal

consult("famio.txt",f1)

%файл "famio.txt" содержит:

%фио("Фадеев","Фиктор","Петрович")

%фио("Иванов","Иван","Иванович")

...............

%фио("Гимазов","Артур","Олегович")

findall(Гриб,гриб(Гриб),Грибы),

findall(Имя_Языка,язык_программирования(_,Имя_Языка),Список),

собрать_фио(СписокФИО).

clauses

собрать_фио(Список):-findall(ФИО,фио(ФИО),Список).

% Список будет состоять из

[ф("Фадеев","Фиктор","Петрович"),ф("Иванов","Иван","Иванович"),...]

3.6.3. Некоторые полезные программы для работы со списками

1. Слияние списков.

Полагаем, что в базе данных facts содержаться два списка (список1, список2), элементами которых являются целые числа. Требуется список1 присоединить к список2. Пусть

список1 есть [5,6,7], а список2 есть [8,9]

domains

список=integer*

facts - f1

список1(список)

список2(список)

predicates

объединить_списки(список,список,список)

goal

список1(Список1),

список2(Список2),!, % А вдруг БД пуста?!

объединить_списки(Список1,Список2,Список3);!.

clauses

объединить_списки([],L,L).

объединить_списки([H|L1],L2,[H|L3]):-

объединить_списки(L1,L2,L3).

Что будет происходить? Поскольку вначале первый список не пуст, Пролог будет пытаться удовлетворить второе правило, очищая первый список. Элементы первого списка пересылаются в стек в оперативной памяти. Когда первый список окажется пустым, становится возможным третьему списку присвоить второй список, и первое правило окажется истинным:

объединить_списки([],[8,9],[8,9]).

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