Упражнение 2.
                            Списъци- основни понятия.
 

1.Константи. Константите в Пролог са два вида атоми и числа. Атоми са имената на предикатите и обектите, те започват с малка буква и като правило съдържат само букви, цифри и _. "?-" и ":-" също са атоми, когато атомите съдържат специални знаци, те като правило съдържат само специални знаци. Ако възникне нужда атомът да започне с главна буква или цифра, то тогава той се огражда в апострофи.

Примери:

а
мъж
=
--->
джон_смит
а1
'Джон-Смит'

Числата в Пролог биват два вида: цели и с плаваща точка при изписването се спазват всички особености от останалите езици за програмиране.

2.Променливи. Променливите започват с главна буква или _ и могат да съдържат букви, цифри или _.

3.Структури. Структурата това е единен обект, състоящ се от други обекти, които ще наричаме компоненти на структурата. Структурите са основно средство в Пролог за представяне на сложни структури от данни, тъй като те се разглеждат като единен обект. Обикновено за тях се използва префиксен запис, като отначало се пише функторът на структурата, който трябва да бъде атом, и след това в кръгли скоби се изписват аргументите,
разделени от запетаи, които могат да бъдат константи, променливи или други структури.

Примери:

има(джон, книга(мечо_пух))
има(джон, А).
има (А, Б).

4.Унификация. Унификацията в Пролог се извършва по следната индуктивна дефиниция, която впоследствие ще разработим по-подробно:
  -две константи се унифицират, ако съвпадат.
  -променлива се унифицира с произволен обект от горните като обектът е константа или структура, тя се остойностява с него, а ако обектът е променлива, то двете се съвместяват.
  -две структури се унифицират, ако функторите им съвпадат и съответните им аргументи се унифицират.

5.Списъци. Списък е наредена последователност от елементи, която може да има произволна дължина. Елементите на списъка могат да бъдат константи, променливи или структури, т. е в частност и списъци. На Пролог това е реализирано по следния начин: списък е или празният списък- [], или структура с функтор "." и имаща два аргумента глава- първият елемент на списъка и опашка, която е списък, който се състои от останалите елементи на списъка. За удобство на Пролог е разработена и друга форма на запис, като елементите на списъка се изреждат заградени в квадратни скоби, разделени със запетаи. Например
[а, б, с , [], [а, е], я(я, А)]
Работата със списъци много често се свежда до разделянето им на глава и опашка, като трябва да се помни, че опашката на списъка винаги е списък. Ето някои примери:
списък                 глава                 опашка
[]                          няма                 няма
[a, b]                    a                        [b]
[a]                        a                        []
[[], b]                   []                       [b]
[a(a,b), a(A)]       a(a,b)                 [a(A)]

Тъй като разделянето на глава и опашка е важна операция за работата със списъци, то в Пролог е въведен и следният запис за списък с глава Г и опашка О: [Г|О] Ето няколко примера за представяне на списъци и унификацията им:

Списък1                   Списък2                      Остойностяване
[]                              [А|О]                          Невъзможна  унификация
[Г]                            [А|О]                          А и Г се съвместяват и О = []
[А, а|О]                    [а, а, в]                        А = а, О = [в]
[А, В|О, Х]                              некоректен запис

Задачи за практикума

1.Уверете се, че сте разбрали как коректно да изписвате списъци, използвайки вградения предикат =, който е верен, когато аргументите му са унифицируеми и има инфиксен запис, се уверете, че сте напълно наясно с унификацията на списъци.

_____

Задачи

1.Напишете предикат, който има два аргумента елемент и списък и е верен, ако елементът принадлежи на списъка:

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

Забележка:1. Ако даден елемент се среща повече от един път в списъка, то този предикат ще се преудовлетворява точно толкова пъти, това ще могат впоследствие да го оправят.
2.Да се обърне внимание на използването на анонимна променлива.
3.Да видят какво ще стане ако разменим местата на клаузите. Наистина предикатът няма да зацикли, защото все някога ще стигне до празния списък и ще пропадне, но ще бъде много по неефективен.
4.Този предикат търси само на първо ниво.

Задачи за практикума, които ще разработим и на следващото упражнение.

1.Напишете предикат, който има два аргумента елемент и списък и е верен, ако елементът е последен елемент на списъка.

2.Напишете предикат, който има два аргумента елемент и списък и е верен, ако елементът принадлежи на списъка, но не само на първо, а на произволно ниво.

3.Напишете предикат, който има три аргумента, първите два са елементите Ел1 и Ел2, а третият е списък и е верен, ако елементите Ел1 и Ел2 принадлежат на списъка в този ред и са последователни.

4.Напишете предикат, който има два аргумента- списъци и е верен, ако първият аргумент е подсписък на втория.

5.Напишете предикат, който има два аргумента- списъци и е верен, ако първият аргумент е списък, в който елементите на втория са изброени в обратен ред.

_______

2.Да се напише предикат, който има три аргумента- списъци и е верен, ако третият е конкатенация на първите два.

append([], L,L).
append([X|L1], L2,[X|L3]):-append(L1,L2,L3).

Забележка:1. Да се забележи, че предикатът може да работи, когато третата променлива е свободна, и тогава в нея ще върне конкатенацията на първите два.
2.Предикатът може да служи и за разделяне при конкретизиран трети аргумент и свободна променлива на мястото на един от първите два. Ако и първите два аргумента са свободни, то при преудовлетворяване ще даде всевъзможните разделяния на третия списък на две.

Задачи за практикума, които ще разработим на следващото упражнение:

1.Пробвайте предиката append, при фиксиран трети аргумент и първите два свободни променливи. Преудовлетворявайте, докато е възможно.

2.Реализирайте предикатите за принадлежност и последен елемент чрез append.