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

1.Принадлежность.

Предикат member(X,Y) означает, что X принадлежит списку Y. Для определения необходимо рассмотреть два случая: X - есть голова списка; X - содержится в хвосте списка. Получаем:

member(X,[X|_]).

member(X,[_|Tail]): - member(X,Tail).

2.Сцепление.

Предикат append(L1,L2,L3) означает, что L3=L1+L2.Для определения необходимо рассмотреть два случая: если первый аргумент пуст, то второй и третий представляют собой один и тот же список; если первый аргумент не пуст, то окончательный список состоит из головы L1, остатка L1 и списка L2. Получаем:

append([],L2,L2).

append([X|Tail],L2,[X|Tail3]): - append(Tail1,L2,Tail3).

3.Добавление. Наиболее простой способ добавить элемент в список - это вставить его в самое начало так, что бы он стал головой. Получаем:

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

4.Удаление. Предикат delete(X,L1,L2) означает, что элемент Х удаляется из списка L1 и получается список L2, т.е. L1=X+L2. Для определения необходимо рассмотреть два случая: Х есть голова списка; Х - в хвосте. Получаем:

delete(X,[X|Tail1],Tail1).

delete(X,[Y|Tail1],[Y|Tail2]):-

delete(X,Tail1,Tail2).

Рассмотрим примеры, демонстрирующие работу со списками.

1.Предикат "принадлежит" представляет собой наименьший полезный пример рекурсивного предиката. При доказательстве предиката member(d,[a,b,c,d,e,f,g]) будет ответ "истино". При доказательстве предиката member(2,[3,a,4,f]) - "ложно".

Каждый раз, когда при согласовании member с базой данных выбирается второе утверждение этого предиката, Пролог рассматривает рекурсивное обращение к предикату member как попытку найти соответствие для некоторой новой его "копии". Это предотвращает путаницу переменных, соответствующих одному употреблению утверждения и соответствующих другому употреблению этого утверждения.

2.Предикат "сцепление". Возможны следующие варианты использования этого предиката.

а) Для разбиения:

? - append(L1,L2,[a,b,c]);

б)Для поиска в списке комбинации элементов, отвечающей некоторому условию, задаваемому в виде образца:

? - append(X,[d|Y],[a,b,c,d,...z]) .

X=[a,b,c]; Y= [e,…,z].

? - append(_,[Month1,"май",Month2|_],

["январь,"февраль",...,"декабрь"]);

Month1= “апрель”; Month2= “июнь”. .

в) Для удаления из списка элементов:

? - L1=[a,b,z,z,c,z,z,z,d,e],

append(L2,[z,z,z|_],L1).

Имеем результат:

L1=[a,b,z,z,c,z,z,z,d,e]

L2=[a,b,z,z,c];

г) Для определения предиката "принадлежит":

member(X,L): - append(_,[X|_],L).

/* X принадлежит L, если список L можно разбить на два списка таким образом, чтобы элемент Х являлся головой второго из них.*/

д) Для определентия предиката "выделение подсписка":

select_list(S,L): -

append(L1,L2,L)

append(S,L3,L2)

/* S - является подсписком L, если L можно разбить на два списка L1 и L2 и L2 можно разбить на два списка S и L3.*/

Например, для цели:

? - select_list(S,[a,b,c])

имеем результат:

S=[];S=[a];S=[a,b];S=[a,b,c];S=[b];...

3.Предикат "удалить". Возможны следующие варианты использования предиката.

а) Для удаления лишь одного вхождения Х, при этом он оставляет остальные в неприкосновенности. Чтобы удалить все, необходимо использовать возврат:

? - delete(a,[a,b,a,a],L).

Имеем результат:

L=[b,a,a]; L=[a,b,a]; L=[a,b,a].

б) Для добавления элементов в список, путем вставления их в произвольные места: ? - delete(a,L,[1,2,3]).

Имеем результат:

L=[a,1,2,3]; L=[1,a,2,3]; L=[1,2,a,3]; L=[1,2,3,a].

в) Можно определить "вставить" через "удалить":

insert(X,L,Big_L): - delete(X,Big_L,L).

г) Можно определить "принадлежит" через "удалить":

member(X,L): - delete(X,L,_).

Рассмотрим примеры предикатов, используемых для обработки списков.

1.Определить количество элементов Y входящих в список X. Для подсчета определим предикат listlen(X,Y).

listlen([],0).

listlen([_|Tail],N): - listlen(Tail,X),N=X+1 .

Для цели: listlen([a,b,c],Y) имеем ответ: Y=3.

2. Определить порядковый номер N элемента Е списка L. Для подсчета определим предикат index(L,N,E ):

index([X|_],1,X): - !.

index([_|Tail],N,X): - N>1,N1=N-1,index(Tail,N1,X).

3. Вывести последовательно все элементы списка, по одному в каждой строке. Для решения этой задачи определим следующие правила:

write_list([]).

write_list([H/Tail]): - write(H),nl,write_list(Tail).

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

4. При работе со списками часто используется встроенный предикат findall. Он имеет следующий вид:

findall(Variable, Goal, List ).

Этот предикат организует список List, состоящий из значений переменной Variable, удовлетворяющих цели Goal.

Пример: Имеется список людей. Требуется определить их средний возраст.

domains

name, address = string

age = integer

list = age*

predicates

person(name, address, age)

sumlist(list, age, integer)

goal

findall(Age, person(_, _, Age), L),

sumlist(L, Sum, N),

Ave = Sum/N,

write("Average =", Ave), nl.

clauses

sumlist([], 0, 0).

sumlist([H|T], Sum, N):- sumlist(T, S1, N1), Sum=H+S1,

N=1+N1.

person("Sherlock Holmes", "22B Baker Street", 42).

person("Pete Spiers", "Apt. 22, 2ist Street", 36).

person("Mary Darrow", "Suite 2, Omega Home", 51).

5. Объекты в списке могут являться списками. При этом все элементы в списке должны принадлежать одному и тому же типу. На Прологе это описывается следующим образом:

domain

objectlist = objects*

objects = symbol*

predicates

member(objects,objectlist).

Упражнения: Реализовать на языке Пролог с использованием списков следующие задачи:

1.Имеется два типа объектов, которые используются для изготовления велосипеда. Это узлы и детали. Узлы состоят из набора деталей. Узел велосипед состоит из деталей: колесо, колесо, рама. Узел колесо состоит из деталей: спица, обод, ступица. Узал рама состоит из деталей: задняя рама, передняя рама. Узел передняя рама состоит из деталей: вилка руль. Узел ступица состоит из деталей: шестерни, ось. Узел ось состоит из деталей: болт гайка. Составить программу, которая для заданного узла перечислит все детали, необходимые для его сборки.

2.Составить программу на Турбо-Прологе, которая в ответ на введённое с терминала предложение (на английском языке) печатает другое предложение, представляющее исходное предложение. Использовать операции преобразования списка. Примерный диалог пользователя с программой выглядит следующим образом:

П.: You are a computer?

М.: I am not a computer.

П.: Do you speak french?

М.: No i speak german.

3.Определить предикат “лин” для “линеаризации” списка путём построения нового списка, не содержащего списков в качестве элементов, но включающего все атомы исходного списка. Например, следующее утверждение должно быть согласовано с базой данных:

лин([a,[b,c]],[[d],[],e]], [a,b,c,d,e]).

4.Составить программу, реализующую основные действия (сложение, вычитание, деление, умножение) над полиномами.

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