|
|
pl:prolog:prolog_lab:listy2 [2009/02/24 12:15] holownia dodanie przechwytywania wyników |
pl:prolog:prolog_lab:listy2 [2019/06/27 15:50] |
====== LAB: Praca z listami w Prologu (cz. 2) ====== | |
| |
===== Ćwiczenie ===== | |
Korzystając z wiedzy zdobytej w [[listy1|pierwszej części laboratorium z listami]] proszę rozwiązać następujące problemy: | |
| |
- zadać cel powodujący usunięcie 3 ostatnich elementów listy L, w wyniku powstaje lista L1, użyć ''sklej''. | |
- zadać cel powodujący usunięcie 3 pierwszych elementów listy L, w wyniku powstaje lista L1, użyć ''sklej''. | |
- zadać cel powodujący usunięcie 3 pierwszych i ostatnich elementów listy L, w wyniku powstaje lista L2, użyć ''sklej''. | |
- zdefiniować predykat ''ostatni1(E,L)'', gdzie E to ostatni element listy L, użyć ''sklej'' (predykat nie jest rekurencyjny). | |
- j.w., ''ostatni2(E,L)'', tylko bez ''sklej'' (predykat jest rekurencyjny). | |
- zdefiniować parę komplementarnych predykatów ''nieparzysta(L)'' oraz ''parzysta(L)'' wypisujących listy o odpowiednio nie/parzystej długości. | |
- zdefiniować predykat ''palindrom(L)'', L jest palindromem, jeżeli czyta się tak samo od przodu i tyłu, np. ''[a,l,a]'', ''[m,a,d,a,m]''. (podpowiedź: można nie/użyć ''odwroc''.) | |
- zdefiniować predykat ''przesun(L1,L2)'', gdzie L2, jest przesuniętą rotacyjnie o jeden element L1, np.: <code prolog> | |
?- przesun([1,2,3,4,5,6,7,8],X),przesun(X,Y),przesun(Y,Z). | |
| |
X = [2, 3, 4, 5, 6, 7, 8, 1] | |
Y = [3, 4, 5, 6, 7, 8, 1, 2] | |
Z = [4, 5, 6, 7, 8, 1, 2, 3] | |
</code> | |
- zdefiniować predykat ''przeloz(L1,L2)'', który zamienia listę liczb (max. 0-9), na listę słów: <code prolog> | |
?- przeloz([1,4,7],X). | |
| |
X = [jeden, cztery, siedem] ; | |
| |
?- przeloz(A,[dwa,osiem,zero]). | |
| |
A = [2, 8, 0] ; </code> posługując się faktami: <code prolog> | |
znaczy(0,zero). znaczy(1,jeden). | |
znaczy(2,dwa). znaczy(3,trzy). | |
znaczy(4,cztery). znaczy(5,piec). | |
znaczy(6,szesc). znaczy(7,siedem). | |
znaczy(8,osiem). znaczy(9,dziewiec). | |
</code> Podpowiedź: predykat ma być rekurencyjny. | |
- zdefiniować predykat ''podzbior(L,Z)'', który sprawdza, czy Z zawiera się w L, oraz wypisuje wszystkie możliwe podzbiory L (jeżeli Z jest niewiadoma). <code prolog> | |
?- podzbior([a,b,c],[c]). | |
| |
Yes | |
?- podzbior([a,b,c],[a,c]). | |
| |
Yes | |
?- podzbior([a,b,c],X). | |
| |
X = [a, b, c] ; | |
X = [a, b] ; | |
X = [a, c] ; | |
X = [a] ; | |
X = [b, c] ; | |
X = [b] ; | |
X = [c] ; | |
X = [] | |
</code> | |
- zdefiniować predykat ''podziel(L,L1,L2)'', który dzieli listę L, na dwa fragmenty L1 i L2, mniej więcej równej długości (z dokładnością do jednego el.), np.: <code prolog> | |
?- podziel([],X,Y). | |
| |
X = [] | |
Y = [] ; | |
| |
?- podziel([1],X,Y). | |
| |
X = [1] | |
Y = [] ; | |
| |
?- podziel([1,2],X,Y). | |
| |
X = [1] | |
Y = [2] ; | |
| |
?- podziel([1,2,3],X,Y). | |
| |
X = [1, 3] | |
Y = [2] ; | |
| |
?- podziel([1,2,3,4],X,Y). | |
| |
X = [1, 3] | |
Y = [2, 4] ; | |
| |
?- podziel([1,2,3,4,5],X,Y). | |
| |
X = [1, 3, 5] | |
Y = [2, 4] ; | |
| |
?- podziel([1,2,3,4,5,6,7,8],X,Y). | |
| |
X = [1, 3, 5, 7] | |
Y = [2, 4, 6, 8] ; | |
</code> | |
- zdefiniować predykat ''splaszcz'', który zamienia dowolnie zagnieżdżoną listę, w listę płaską (której el. nie są listami). (podstawowe rozwiązanie działa bez nawrotów - nie należy naciskać '';'') <code prolog> | |
?- splaszcz([[a],b,c],X). | |
| |
X = [a, b, c] | |
| |
?- splaszcz([[a],[b,[d]],c],X). | |
| |
X = [a, b, d, c] | |
| |
?- splaszcz([a,b,c],X). | |
| |
X = [a, b, c] | |
| |
?- splaszcz(a,X). | |
| |
X = [a] | |
</code> | |
- Napisz program który obliczy na jakie monety można rozmienić zadaną sumę pieniędzy. | |
* Zdefiniuj nominały monet: np. ''moneta(1)'' oznacza monetę jednozłotową, | |
* Predykat rozmieniający powinien mieć dwa argumenty: ''rozmien/2'', gdzie pierwszy to kwota, a drugi lista nominałów monet na jakie można rozmienić kwotę; uwaga: predykat będzie niedeterministyczny. | |
| |
===== Przechwytywanie wyników ===== | |
| |
==== Temat: Użycie predykatów bagof, setof i findall ==== | |
Z Prologiem dostarczonych jest kilka predykatów przydatnych przy obróbce wyników wyszukiwania. | |
| |
Predykat //bagof/3//, użyty jako ''bagof(X,P,L)'' buduje listę ''L'', złożoną z takich ''X'', że spełnione jest ''P''. | |
| |
Podobnie działa //setof/3//, jednak powstała lista jest posortowana i nie zawiera ew. duplikatów. | |
| |
Specjalny operator ''^'' pozwala na modyfikowanie zapytania i jest równoważny kwantyfikacji egzystencjalnej, np. zakładając istnienie bazy faktów zdefiniowanej za pomocą predykatu ''a/2'': | |
* ''bagof(X,Y^a(X,Y),L)'' spowoduje znalezienie listy L na ktorej beda znajdować się wartości X niezależnie od tego jaką wartość przyjmuje Y (dokładnie jedno rozwiązanie). | |
* ''bagof(X,a(X,Y),L)'' spowoduje znalezienie listy L na ktorej beda znajdować się wartości X dla konkretnej (znalezionej) wartości Y (wiele rozwiązań, lista dla każdej wartości Y). | |
| |
| |
Predykat //findall/3// wymusza wyszukanie wszystkich możliwych wyników. | |
| |
| |
==== Ćwiczenie: Użycie predykatów bagof, setof i findall ==== | |
Wczytać program z 1. zajęć {{rodzina1.pl}} | |
| |
Sprawdzić działanie: | |
| |
?- rodzic(X,robert). | |
| |
?- bagof(X,rodzic(X,robert),L). | |
| |
Sprawdzić działanie: | |
| |
?- bagof(X,ojciec(tomek,X),L). | |
| |
?- setof(X,ojciec(tomek,X),L). | |
| |
Następnie: | |
| |
?- bagof(X,Y^ojciec(X,Y),L). | |
| |
?- setof(X,Y^ojciec(X,Y),L). | |
| |
Oraz: | |
| |
?- bagof(X,ojciec(X,Y),L). | |
| |
?- findall(X,ojciec(X,Y),L). | |
| |
===== Komentarze ===== | |
Z braku lepszego miejsca tutaj studenci wpisują komentarze natury ogólnej do tego lab. 8-) | |
| |
--- //[[gjn@agh.edu.pl|Grzegorz J. Nalepa]] 2008/02/20 14:34// | |
| |