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

2.5 Контрольні запитання

2.5.1 Що таке рекурсія? Чому вона така важлива у Пролозі?

2.5.2 Які методи рекурсії вам відомі? Яку роль відіграють у рекурсії граничні умови? Що буде, якщо значення аргументів рекурсивного виклику не буде сходитись до значень аргументів граничної умови?

2.5.3 Який метод рекурсії вивчили ви? Опишіть роботу цього методу.

2.5.4 Як висхідна рекурсія використовує стек і механізм зчеплення?

2.5.5 Чи передається через анонімну змінну у рекурсивному виклику значення?

2.5.6 Які ви знаєте стандартні предикати роботи з рядками, з якими типами даних вони працюють?

2.5.7 Вказати режими роботи стандартних предикатів роботи з рядками.

3 Лабораторна робота № 3 робота зі списками методом низхідної рекурсії

3.1 Мета роботи

Мета роботи:

  • навчитися використовувати при програмуванні основну операцію на списках та стандартні процедури обробки списків;

  • навчитися писати та налагоджувати програми, які оброблюють списки за допомогою низхідної рекурсії.

3.2 Методичні вказівки до виконання лабораторної роботи

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

Задавайте ціль для стандартної процедури Append різними способами і перевіряйте, як це впливає на роботу процедури Append.

Приклад 1

Ввести список цілих чисел. Порівняти перший і третій елементи списків. Якщо перший елемент більше, то залишити ці елементи на місцях. Інакше поміняти їх місцями.

Domains

List=integer*

Predicates

nondeterm Do(list, list)

Goal

Readterm(list,L),do(L, L1),!.

Clauses

Do([H1,H2,H3| T],L1):- H1>H3,L1= [H1,H2,H3| T],!;

L1=[H3,H2,H1|T].

Do(L,L1):-write("Кількість елементів списку <3",L),nl,L1=[].

Предикат Readterm вводить список з клавіатури, привласнює його змінній L і передає список в предикат do.

Введемо для прикладу список [12, 35, 41, 6, 2].

При зіставленні предикату do з цілі з умовним твердженням виконуються таке зіставлення:

[12, 35, 41, 6, 2] = [H1,H2,H3| T].

Змінні одержують такі значення: H1=12, H2=35, H3= 41, T=[6,2].

При вірній умові H1>H3 вільній змінній L1 привласнюється список [12, 35, 41, 6, 2]. При не вірній умові вільній змінній L1 привласнюється список [41, 35, 12, 6, 2].

Зверніть увагу, що порядок елементів нового списку задається порядком голів списку. А операція „|” працює залежно від конкретизації змінних на приєднання елементу чи на відокремлювання перших елементів списку.

Приклад 2

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

Domains

List = real*

Predicates

nondeterm in (list ,list, real)

Goal

write("Введіть спиок за зростанням "),nl,

Readterm(list, L), write("Введіть число "),

readreal(El),in (L, New_List,El),!.

Clauses

In([],[El],El):-!.

In([H1,H2| T], [H1,El,H2| T], El):- H1< El, El<H2,!.

In([H|T],[El, H|T],El):-El<H,!.

In([H|T],[H, El|T],El):-T=[],!.

In([H|T], New_List, El):-!,in(T, T1,El),

New_List = [H|T1].

Програма написана низхідним методом рекурсії.

Програма має 4 граничних умови. Для певного списку і елементу працює тільки одна умова:

  • перша умова вставляє в порожній список елемент;

  • друга умова вставляє елемент між двома елементами списку;

  • третя умова вставляє елемент перед першим елементом списку;

  • четверта умова вставляє елемент в кінець списку.

Рекурсивна умова відокремлює елемент списку і викликає процедуру з хвостом списку.

Конкретизовані змінні зберігаються в стеку автоматично. Тому елемент списку зберігається в стеку.

Дія повторюється до тих пір, поки не спрацює одна з граничних умов.

Після чого до хвосту списку додається в початок елемент списку зі стеку. Дії повторюються до тих пір, поки стек не спорожніє.

Рекурсивна умова може записуватись також в такому вигляді:

In([H|T], [H|T1], El):-!,in(T, T1,El).

Стандартні процедури обробки списків

Стандартні процедури відомі з літератури, проте їх треба самому вказувати в програмі.

Процедура belongs – перевіряє, чи належить елемент списку.

Domains

list=char*

Predicates

belongs(char, list)

Goal

belongs (‘с’, ['а','b','с'] ). /* Чи належить символ 'с' списку

['а','b','с'] */

Clauses

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

belongs ( X, [ _ | T] ):– !,belongs ( X, T ). (2)

Якщо голова списку співпадає з вказаним елементом, то працює факт 1, інакше працює правило 2, елемент шукається у хвості списку.

Процедура append – працює у трьох режимах.

Режим роботи процедури залежить від цілі:

  1. Ціль: append ( [ 1, 2 ],[ 3, 4 ], L ). Режим: з'єднання двох списків.

Результат: список L=[ 1, 2, 3, 4 ];

  1. Ціль: append ( Do, [ 2 | Pisly], [ 1, 2, 3] ).Режим: розподіл списку на два списки за даною ознакою.

Результат: Do=[ 1 ], Pisly =[ 3 ];

  1. Ціль: append ( L1, L2, [ 1, 2, 3 ]). Режим: розподіл списку на два списки (усі можливі варіанти). Візуальний Пролог сам перебирає всі розв’язки.

Результати: L1=[ ], L2=[ 1, 2, 3 ];

L1=[ 1 ], L2=[ 2, 3 ];

L1=[ 1, 2 ], L2=[ 3 ];

L1=[ 1, 2, 3 ], L2=[ ].

Процедура Append

Розглянемо другий режим роботи процедури append. Задамо ціль таким чином, щоб елементи списку [1,2,3,4], що стоять перед числом 3 віднести до списку L1, а елементи після числа 3 віднести до списку Т(випадок b).

Domains

list=integer*

Predicates

append(list, list, list)

Clauses

append ( [ ], L, L ).

append ( [F| L1 ], L2, [F | L4 ] ):-!, append ( L1, L2, L4).(1)

Goal

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

Процедури delete і delete1 – вилучають вказаний елемент із списку.

Процедура delete1 – вилучає вказаний елемент, який перший зустрівся в списку.

Domains

list=integer*

Predicates

delete1(integer, list, list)

Goal

delete1 ( 2, [ 1, 2, 2 ], L ).

Clauses

delete1( _, [ ], [ ] ):-!. (1)

delete1( X, [X | L1 ], L1 ):-!. (2)

delete1( X, [ H | L1], [H | L2 ] ):- delete1(X, L1, L2 ). (3)

Вилучити першу 2, що зустрілася у списку [1,2,2]. Результат розміщується у змінну L=[1,2].

Перше умовне твердження істинне, якщо елемент не знайдено. Результат співпадає з вхідним списком.

Друге правило вилучає знайдений елемент. Залишок списку переноситься у новий список.

Третє правило переносить голову списку у новий список, якщо вона не співпадає з елементом, який вилучається. Після цього продовжується пошук елементу, який вилучається.

Процедура delete2 – вилучає всі елементи списку, що дорівнюють вказаному.

Domains

list=integer*

Predicates

delete2(integer, list, list)

Goal

delete2 ( 2, [ 1, 2, 2 ], L ).

Clauses

delete2( _, [ ], [ ] ):-!. (1)

delete2(X, [ X | L1 ], L2 ):-!, delete2( X, L1,L2 ). (2)

delete2( X, [ H | L1], [ H | L2 ] ):- delete2( X, L1,L2 ). (3)

Процедура delete2 відрізняється від процедури delete1 тим, що після того, як вилучено вказаний елемент, вона продовжує пошук вказаного елемента у хвості списку і вилучає всі елементи, що дорівнюють вказаному.

3.2.2 Виконайте завдання свого варіанту за № в журналі.

Продумайте, які стандартні процедури ви можете використати у вашій програмі. Пам'ятайте, що ваша програма буде компактна, якщо ви будете використовувати можливості Прологу - відокремлювати перший елемент від списку у голові правила.

Налагодьте вашу програму за допомогою трасування. Під час трасування переконайтесь, що ваша програма не має зайвих розв'язків або не виконує непотрібних дій.

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