Różnice między wybraną wersją a wersją aktualną.
Poprzednia rewizja po obu stronachPoprzednia wersjaNowa wersja | Poprzednia wersja | ||
notatki:prolog [2025/05/13 22:49] – administrator | notatki:prolog [2025/05/27 14:56] (aktualna) – administrator | ||
---|---|---|---|
Linia 1: | Linia 1: | ||
- | ====== Prolog ====== | + | ====== Prolog: Podstawy programowania logicznego |
===== Programy do uruchomienia Prologa ===== | ===== Programy do uruchomienia Prologa ===== | ||
Linia 44: | Linia 44: | ||
Przykłady: | Przykłady: | ||
* Jeśli mamy fakt '' | * Jeśli mamy fakt '' | ||
- | * Jeśli mamy zapytanie '' | + | * Jeśli mamy zapytanie '' |
</ | </ | ||
Linia 381: | Linia 381: | ||
'' | '' | ||
+ | ====== Struktury listowe w języku Prolog ====== | ||
+ | |||
+ | Struktury listowe w języku **Prolog** stanowią podstawowy mechanizm reprezentacji zbiorów danych. Listy są strukturami rekurencyjnymi, | ||
+ | |||
+ | ===== Definicja listy ===== | ||
+ | |||
+ | Lista w Prologu to uporządkowany zbiór elementów, zapisany w nawiasach kwadratowych i oddzielony przecinkami: | ||
+ | |||
+ | <code prolog> | ||
+ | [el1, el2, el3] | ||
+ | </ | ||
+ | |||
+ | Lista może być również pusta: | ||
+ | |||
+ | <code prolog> | ||
+ | [] | ||
+ | </ | ||
+ | |||
+ | ===== Operacje na listach ===== | ||
+ | |||
+ | ====== Dostęp do elementów ====== | ||
+ | |||
+ | Lista może być rozbita na głowę (pierwszy element) i ogon (reszta listy): | ||
+ | |||
+ | <code prolog> | ||
+ | [H|T] | ||
+ | </ | ||
+ | |||
+ | - **H** – głowa listy (head) | ||
+ | - **T** – ogon listy (tail) | ||
+ | |||
+ | Przykład: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- [H|T] = [1,2,3]. | ||
+ | H = 1, | ||
+ | T = [2,3]. | ||
+ | </ | ||
+ | |||
+ | ====== Sprawdzanie przynależności ====== | ||
+ | |||
+ | Operator `member/2` sprawdza, czy element należy do listy: | ||
+ | |||
+ | <code prolog> | ||
+ | member(X, [a,b,c]). | ||
+ | </ | ||
+ | |||
+ | ====== Łączenie list ====== | ||
+ | |||
+ | Operator `append/3` służy do łączenia dwóch list: | ||
+ | |||
+ | <code prolog> | ||
+ | append([1, | ||
+ | Result = [1,2,3,4]. | ||
+ | </ | ||
+ | |||
+ | ====== Długość listy ====== | ||
+ | |||
+ | Predykat `length/2` służy do określania długości listy: | ||
+ | |||
+ | <code prolog> | ||
+ | length([a, | ||
+ | N = 3. | ||
+ | </ | ||
+ | |||
+ | ===== Rekurencja na listach ===== | ||
+ | |||
+ | Ze względu na rekurencyjny charakter list, większość algorytmów operujących na listach korzysta z rekurencji. | ||
+ | |||
+ | Przykład sumowania elementów listy: | ||
+ | |||
+ | <code prolog> | ||
+ | sum([], 0). | ||
+ | sum([H|T], S) :- | ||
+ | sum(T, S1), | ||
+ | S is H + S1. | ||
+ | </ | ||
+ | |||
+ | ===== Lista jako struktura danych ===== | ||
+ | |||
+ | Listy mogą zawierać zmienne, inne listy, a także złożone struktury: | ||
+ | |||
+ | <code prolog> | ||
+ | [[a,b], [c,d]] | ||
+ | </ | ||
+ | |||
+ | Mogą także być niedomknięte (ang. open-ended lists): | ||
+ | |||
+ | <code prolog> | ||
+ | [1,2|X] | ||
+ | </ | ||
+ | |||
+ | Jest to przydatne przy konstruowaniu dynamicznych list. | ||
+ | |||
+ | ===== Wypisywanie elementów listy ===== | ||
+ | |||
+ | Predykat wypisujący każdy element listy w osobnej linii: | ||
+ | |||
+ | <code prolog> | ||
+ | print_list([]). | ||
+ | print_list([H|T]) :- | ||
+ | write(H), nl, | ||
+ | print_list(T). | ||
+ | </ | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- print_list([apple, | ||
+ | apple | ||
+ | banana | ||
+ | cherry | ||
+ | </ | ||
+ | |||
+ | ===== Wyodrębnianie pierwszego elementu listy ===== | ||
+ | |||
+ | Aby uzyskać pierwszy element listy, możemy użyć dopasowania wzorców (pattern matching) z użyciem operatora |. | ||
+ | |||
+ | Przykładowy predykat: | ||
+ | |||
+ | <code prolog> | ||
+ | first_element([H|_], | ||
+ | </ | ||
+ | |||
+ | - **[H|_]** – dopasowuje listę, gdzie `H` to pierwszy element, a `_` ignoruje resztę. | ||
+ | - **H** – zmienna zwracająca pierwszy element. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- first_element([a, | ||
+ | X = a. | ||
+ | </ | ||
+ | |||
+ | ===== Wyodrębnianie drugiego elementu listy ===== | ||
+ | |||
+ | Aby uzyskać drugi element listy, możemy użyć dopasowania wzorców, omijając pierwszy element. | ||
+ | |||
+ | Predykat: | ||
+ | |||
+ | <code prolog> | ||
+ | second_element([_, | ||
+ | </ | ||
+ | |||
+ | - **[_, Second|_]** – ignoruje pierwszy element (`_`), przypisuje drugi do zmiennej `Second`, a resztę ignoruje. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- second_element([x, | ||
+ | X = y. | ||
+ | </ | ||
+ | |||
+ | ===== Wyodrębnianie ostatniego elementu listy ===== | ||
+ | |||
+ | Aby uzyskać ostatni element listy, możemy wykorzystać rekurencyjne dopasowanie wzorców. | ||
+ | |||
+ | Predykat: | ||
+ | |||
+ | <code prolog> | ||
+ | last_element([X], | ||
+ | last_element([_|T], | ||
+ | last_element(T, | ||
+ | </ | ||
+ | |||
+ | - **[X]** – dopasowanie jednoelementowej listy (ostatni element). | ||
+ | - **[_|T]** – rekurencyjne przeszukiwanie ogona listy, aż zostanie tylko jeden element. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- last_element([a, | ||
+ | X = d. | ||
+ | </ | ||
+ | Wywołania rekurencyjne: | ||
+ | {{.: | ||
+ | |||
+ | ===== Znajdowanie elementu w liście ===== | ||
+ | |||
+ | Aby sprawdzić, czy dany element znajduje się w liście, można skorzystać z wbudowanego predykatu `member/2`, albo zdefiniować własną wersję. | ||
+ | |||
+ | Wersja oparta na rekurencji: | ||
+ | |||
+ | <code prolog> | ||
+ | in_list([X|_], | ||
+ | in_list([_|T], | ||
+ | in_list(T, X). | ||
+ | </ | ||
+ | |||
+ | - **[X|_]** – dopasowanie, | ||
+ | - **[_|T]** – rekurencyjne przeszukiwanie ogona listy. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- in_list([1, 2, 3, 4], 3). | ||
+ | true. | ||
+ | |||
+ | ?- in_list([a, b, c], d). | ||
+ | false. | ||
+ | </ | ||
+ | |||
+ | Alternatywa: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- member(3, [1,2,3,4]). | ||
+ | true. | ||
+ | </ | ||
+ | |||
+ | ===== Sprawdzanie, | ||
+ | |||
+ | Predykat sprawdzający, | ||
+ | |||
+ | <code prolog> | ||
+ | sorted_asc([]). | ||
+ | sorted_asc([_]). | ||
+ | sorted_asc([X, | ||
+ | X =< Y, | ||
+ | sorted_asc([Y | T]). | ||
+ | </ | ||
+ | |||
+ | - **[]** i **[ _ ]** — lista pusta lub jednoelementowa jest uporządkowana. | ||
+ | - **[X, Y | T]** — sprawdzamy, czy pierwszy element jest mniejszy lub równy drugiemu, a następnie rekurencyjnie resztę listy. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- sorted_asc([1, | ||
+ | true. | ||
+ | |||
+ | ?- sorted_asc([1, | ||
+ | false. | ||
+ | </ | ||
+ | |||
+ | ===== Wstawianie elementu do listy uporządkowanej rosnąco ===== | ||
+ | |||
+ | Predykat, który wstawia element `X` do posortowanej listy rosnącej `List`, zwracając nową listę `Result`, również uporządkowaną rosnąco: | ||
+ | |||
+ | <code prolog> | ||
+ | insert_sorted(X, | ||
+ | insert_sorted(X, | ||
+ | X =< H. | ||
+ | insert_sorted(X, | ||
+ | X > H, | ||
+ | insert_sorted(X, | ||
+ | </ | ||
+ | |||
+ | - Jeśli lista jest pusta, nowa lista to `[X]`. | ||
+ | - Jeśli `X` jest mniejsze lub równe pierwszemu elementowi `H`, wstawiamy `X` przed `H`. | ||
+ | - W przeciwnym razie rekurencyjnie wstawiamy `X` w ogon listy. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- insert_sorted(3, | ||
+ | Result = [1, 2, 3, 4, 5]. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Sortowanie listy metodą wstawiania ===== | ||
+ | |||
+ | Predykat sortujący listę numeryczną rosnąco za pomocą algorytmu sortowania przez wstawianie (*insertion sort*). | ||
+ | |||
+ | Definicja: | ||
+ | |||
+ | <code prolog> | ||
+ | insert_sorted(X, | ||
+ | insert_sorted(X, | ||
+ | X =< H. | ||
+ | insert_sorted(X, | ||
+ | X > H, | ||
+ | insert_sorted(X, | ||
+ | |||
+ | insertion_sort([], | ||
+ | insertion_sort([H|T], | ||
+ | insertion_sort(T, | ||
+ | insert_sorted(H, | ||
+ | </ | ||
+ | |||
+ | Opis działania: | ||
+ | - `insert_sorted/ | ||
+ | - `insertion_sort/ | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- insertion_sort([4, | ||
+ | Sorted = [1, 2, 3, 4]. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Obliczanie długości listy ===== | ||
+ | |||
+ | Predykat `length_list/ | ||
+ | |||
+ | Definicja: | ||
+ | |||
+ | <code prolog> | ||
+ | length_list([], | ||
+ | length_list([_|T], | ||
+ | length_list(T, | ||
+ | N is N1 + 1. | ||
+ | </ | ||
+ | |||
+ | - **[]** – pusta lista ma długość 0. | ||
+ | - **[_|T]** – ignorujemy pierwszy element i rekurencyjnie liczymy długość ogona listy, zwiększając wynik o 1. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- length_list([a, | ||
+ | N = 4. | ||
+ | </ | ||
+ | |||
+ | Alternatywnie, | ||
+ | |||
+ | <code prolog> | ||
+ | ?- length([a, b, c, d], N). | ||
+ | N = 4. | ||
+ | </ | ||
+ | |||
+ | ===== Sumowanie elementów listy ===== | ||
+ | |||
+ | Predykat `sum_list/ | ||
+ | |||
+ | Definicja: | ||
+ | |||
+ | <code prolog> | ||
+ | sum_list([], | ||
+ | sum_list([H|T], | ||
+ | sum_list(T, Rest), | ||
+ | Sum is H + Rest. | ||
+ | </ | ||
+ | |||
+ | - **[]** – suma pustej listy to 0. | ||
+ | - **[H|T]** – dodajemy bieżący element `H` do sumy pozostałych elementów `T`. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- sum_list([1, | ||
+ | S = 10. | ||
+ | </ | ||
+ | |||
+ | Można również użyć wbudowanego predykatu `sum_list/ | ||
+ | |||
+ | <code prolog> | ||
+ | ?- sum_list([1, | ||
+ | S = 10. | ||
+ | </ | ||
+ | |||
+ | ===== Średnia arytmetyczna elementów listy ===== | ||
+ | |||
+ | Predykat `average_list/ | ||
+ | |||
+ | Wymaga dwóch pomocniczych predykatów: | ||
+ | * `sum_list/ | ||
+ | * `length_list/ | ||
+ | |||
+ | Definicja: | ||
+ | |||
+ | <code prolog> | ||
+ | sum_list([], | ||
+ | sum_list([H|T], | ||
+ | sum_list(T, Rest), | ||
+ | Sum is H + Rest. | ||
+ | |||
+ | length_list([], | ||
+ | length_list([_|T], | ||
+ | length_list(T, | ||
+ | N is N1 + 1. | ||
+ | |||
+ | average_list(List, | ||
+ | sum_list(List, | ||
+ | length_list(List, | ||
+ | Length > 0, | ||
+ | Avg is Sum / Length. | ||
+ | </ | ||
+ | |||
+ | Opis działania: | ||
+ | - Najpierw obliczamy sumę elementów listy. | ||
+ | - Następnie obliczamy jej długość. | ||
+ | - Obliczamy średnią jako `Sum / Length`. | ||
+ | |||
+ | Przykład użycia: | ||
+ | |||
+ | <code prolog> | ||
+ | ?- average_list([2, | ||
+ | A = 5.0. | ||
+ | </ | ||
+ | |||
+ | Uwaga: predykat sprawdza, czy długość listy jest większa od zera, aby uniknąć dzielenia przez zero. | ||