СПИСКИ


Списки — это объекты, которые имеют конечное число элементов. Объявляют их добавляя «*» (звездочку) в конце предварительно определяемого типа.
domains
intlist=integer* /*Список целых чисел*/

Список — это рекурсивный комбинированный объект, составленный из головы и хвоста. Голова — это первый элемент списка, а хвост – это все остальное (без первого элемента). Хвост списка — всегда список. Голова списка всегда — элемент. Список может иметь 0 или более элементов; пустой список записывается [].
В Прологе список рассматривается как частный случай бинарного дерева:

Элементы списка могут быть любыми, включая и другие списки. Все элементы списка должны принадлежать одному и тому же типу. В Турбо Прологе нельзя смешивать типы в списке.
Для разделения головы и хвоста в списке используются разделители (запятая, [ и |); В голове списка можно выделить несколько элементов, например, список [a, b, c, d] может быть записан как

[a|[b, c, d]] или
[a, b|[c, d]] или
[a, b, c|[d]] или
[a|[b|[c, d]]] или
[a|[b|[c|[d]]]] или даже
[a|[b|[c|[d|[]]]]]

Пустой список нельзя разделить на голову и хвост.
Порядок элементов в списке существенен. Один и тот же объект может встречаться в списке несколько раз.
Главный способ обработки списка — это просмотр его и обработка каждого элемента, пока не будет достигнут конец. Алгоритму этого типа обычно нужно два предложения. Первое из которых говорит, что делать с обычным списком (списком, который можно разделить на голову и хвост). Второе говорит, что делать с пустым списком. Т.е., работа со списком состоит из рекурсивного выделения головы (и, обычно, его обработки), до тех пор, пока список не станет пустым.

/* Листинг программы Lab4_1.pro*/
domains
intlist=integer*

predicates

cr_list (intlist,intlist) % Создание списка
do % Главная процедура
list (intlist) % Вывод списка — правая рекурсия
list1 (intlist) % Вывод списка — левая рекурсия
member (integer,intlist) % Является ли элемент членом списка
length(intlist,integer) % вычисление длины списка (левая рекурсия)
length_of(intlist,integer,integer) % вычисление длины списка (правая рекурсия)
app_el (integer,intlist,intlist) % Добавить элемент в начало списка
ins (integer,intlist,intlist) % Добавить элемент в произвольную позицию списка
del_el (integer,intlist,intlist) % удаление первого вхождения элемента в список
delete (integer,intlist,intlist) % удаление всех вхождений элементов в список
append(intlist, intlist, intlist) % Добавить второй список в конец первого списка
sublist(intlist,intlist) % подсписок списка
perest(intlist,intlist) % перестановки

clauses

list([]).
list([X|XS]):-write(X,» «),list(Xs).

list1([]).
list1([X|T]):-list1(T),write(X,» «).

member(X,[X|Xs]).
member(X,[Y|Ys]):-member(X,Ys).

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

cr_list(List,NewList):-readint(X),
X<>999,!,
app_el(X,List,TempList),
cr_list(TempList,Newlist).

cr_list(List,List).

length([],0).
length([_|Xs],N):- length(Xs,N1),N=N1+1.

length_of([], Result, Result).
length_of([_|T], Result, K):-
NewK = K + 1,
length_of(T, Result, NewK).

append([], List, List).
append([X|L1], List2, [X|L3]):- append(L1, List2, L3).

del_el(X,[X|T],T).
del_el(X,[Y|T],[Y|T1]):-
del_el(X,T,T1).

delete(X,[X|Xs],Ys):-delete(X,XS,Ys).
delete(Z,[X|Xs],[X|Ys]):-delete(Z,Xs,Ys).
delete(X,[],[]).

sublist(S,L):- append(L1,L2,L),append(S,L3,L2).

ins(X,List,Biglist):-del_el(X,Biglist,List),list(Biglist),nl,fail.

perest([],[]).
perest(L,[X|P]):- del_el(X,L,L1),perest(L1,P).

do:-
write(«Введите элементы списка. Признак окончания ввода — 999.»),nl,
cr_list([],Nlist),!,nl,
list(NList),nl,
length(NList,N),
write(«Количество элементов списка=»,N),nl.

/*goal
do.
*/

Рассмотрим предикат append, определенный в программе Lab4_1.PRO. Загрузите программу и закомментируйте секцию goal. Запустите следующие целевые утверждения:

append([1, 2, 3], [5, 6], L).
append([1, 2], [3], L).

В Прологе один и тот же предикат может иметь несколько вариантов использования.
Классические предикаты Пролога member (элемент списка) и append (добавить элемент в список) дают возможность проверить, есть ли элемент в списке, и проверить есть, ли один список в другом соответственно.
Рассматривая append с декларативной точки зрения, вы определили отношение между тремя списками. Это отношение все равно останется, если List1 и List3 — известны, а List2 — нет. Оно также справедливо, если известен только List3. Например, чтобы определить, какие из двух списков можно обьединить для того, чтобы получить известный список, надо составить целевое утверждение следующей формы:

append(L1, L2, [1, 2, 4]).

По этому целевому утверждению Турбо Пролог найдет следующие решения:

L1 = [], L2 = [1,2,4]
L1 = [1], L2 = [2,4]
L1 = [1,2], L2 = [4]
L1 = [1,2,4], L2 = []
4 Solutions

Можно также применить append, чтобы определить какой список можно подсоединить к [3, 4], чтобы получить список [1, 2, 3, 4]. Запустите целевое утверждение:

append(L1, [3,4], [1,2,3,4]).

Турбо Пролог найдет решение:

L1 = [1,2].

Предикат append определил отношение между входным набором и выходным набором таким образом, что отношение применимо в обоих направлениях. Задавая такое отношение, получаем ответы на вопросы: Как относится выход с данным входом? Или Как относится вход с данным выходом?
Состояние аргументов при вызове предиката передается как поток параметров. Аргумент, который присваивается или назначается в момент вызова, называется входным аргументом и обозначается буквой (i); а свободный аргумент — это выходной аргумент, обозначается буквой (o).
У предиката append есть возможность манипулировать и переставлять части, как необходимо. Однако, не для всех предикатов имеется возможность быть вызванными с потоком параметров. Когда в предложении Пролога можно работать с потоком параметров, оно называется инверсным предложением. Когда вы записываете собственные предложения в Турбо Прологе, помните, что инверсное предложение имеет дополнительные преимущества, и создание инверсных предложений добавляет мощности предикатам, которые вы пишете.

Загрузка...