Home Termíny Cvičení Projekty Rezervace termínu |
Osnova
- seznamy
- řezy
- akumulátor
- modelové příklady (dopředná a zpětná
konstrukce seznamu, cyklus)- NEW stránka s řešením
Procvičení seznamů
- Které z následujích termů jsou seznamem a které ne?
a) [] b) [1] c) [1,2] d) [H|T] e) [1|2] f) [1,2,3|[4]] g) .(1,[]) h) .(1,2) i) .(1,2,3) j) .(1,.(2,.(3))) k) [X] l) [[X]] m) [1,2,3,4]
- Které dvojice předchozích termů lze unifikovat?
- K čemu lze použít následující predikát s/1?
s([]). s([_|T]):-s(T).
- Napište predikát selekce(Sez,Sez_bez_prom), který přepíše ze seznamu Sez do seznamu Sez_bez_prom jen ty prvky, které nejsou volné promenné. [Pomůcka: použijte vestavěný (built-in) predikát nonvar/1]
- Otestujte Váš prográmek z předchozího úkolu na tomto příkladu:
selekce([22,Z,z,7,s(1),Prvek,b],Vysledek)
Dokážete napsat jinou verzi tohoto prográmku tak, aby bylo pořadí prvků v seznamu Vysledek opačné, než je teď?
- Napište predikát rozdil(Seznam,Zakazane_prvky,Vysledek), který přepíše ze seznamu Seznam do seznamu Vysledek jen ty prvky, které nejsou v seznamu Zakazane_prvky, v podstatě se jedná o rozdíl dvou (uspořádaných) množin. [Pomůcka: použijte predikát member/2 probraný v přednásce nebo nějakou jeho modifikaci]
Vyzkoušejte si napsat i jiné množinové operátory (sjednocení, prunik, součin,...) pro množiny reprezentované seznamy.
Procvičení řezu
- Je dán následující program:
r(X):-write(r1). r(X):-p(X),write(r2). r(X):-write(r3). p(X):-write(p1). p(X):-a(X),b(X),!,c(X),d(X),write(p2). p(X):-write(p3). a(X):-write(a1). a(X):-write(a2). b(X):- X > 0, write(b1). b(X):- X < 0, write(b2). c(X):- X mod 2 =:= 0, write(c1). c(X):- X mod 3 =:= 0, write(c2). d(X):- abs(X) < 10, write(d1). d(X):-write(d2).Prozkoumejte trasy výpočtu a navracení např. pomocí následujících dotazů:a) X=1,r(X). b) X=3,r(X). c) X=0,r(X). d) X= -6,r(X).Vždy si středníkem vyžádejte navracení. Všimnete si zejména:
- řez v predikátu p/1 neovlivní alternativy predikátu r/1
- dokud nebyl proveden řez, alternativy predikátu a/1 se uplatňují, př. neúspěch b/1 v dotazu c)
- při neúspěchu cíle za řezem se výpočet navrací až k volající proceduře r/1, dotaz a)
- alternativy vzniklé po provedení řezu se zachovávají - další možnosti predikátu c/1 v dotazech b) a d)
- Jaký je rozdíl mezi následujícími definicemi predikátů member/2. Ve kterých odpovědích se budou lišit?
mem1(H,[H|_]). mem1(H,[_|T]):-mem1(H,T). mem2(H,[H|_]):-!. mem2(H,[_|T]):-mem2(H,T). mem3(H,[K|_]):-H==K. mem3(H,[K|T]):-H\==K,mem3(H,T).
- Je tato definice predikátu max/3 korektní?
max(X,Y,X):-X>=Y,!. max(X,Y,Y).Uveďte dvě možnosti opravy, se zachováním použití řezu a bez.
Procvičení techniky akumulátor
- Uvažujme program na součet prvků seznamu
suma([],0). suma([H|T],S):-suma(T,S1),S is S1+H.Pokud chceme dosáhnout optimalizaci posledního voláni, proč nestačí prohodit cíle v poslední klauzuli?suma([H|T],S):-S is S1+H,suma(T,S1).
- Následující program při volání S=[1,2,3],suma(S,0) vypíše součet prvků seznamu S na obrazovku:
suma([],V):-write(V),nl. suma([H|T],S):-S1 is H+S,suma(T,S1).Upravte program tak, aby vracel výsledek (součet prvků seznamu) ve svém druhém argumentu místo výpisu na obrazovku, při zachování rekurzivního volání na konci klauzule (LCO).
Modelové příkladyKopie seznamu copy(S,T):
copy([],[]). copy([H|S],[H|T]):-copy(S,T). /* prime poradi - prvek je pridan v hlave pravidla */Obrácení seznamu rev(S,T):rev(S,T):-rev(S,[],T). /* zavedeni akumulatoru */ rev([],T,T). rev([H|S],A,T):-rev(S,[H|A],T). /* obracene poradi - prvek je pridan v tele pravidla */Cyklus s využitím optimalizace posledního volání (LCO - Last Call Optimization) technikou akumulátoru:Příklad: Výpočet faktoriálu
predikát fact(N,F), pro jehož argumenty platí F=N!
- výpočet F jako N*(N-1)*(N02)*...*1
fact(N,F):-fact(N,1,F). /* inicializace akumulatoru */ fact(0,F,F). /* ukoncovaci pravidlo */ fact(N,A,F):- N>0, /* snazime se nejprve provest testy */ N1 is N-1, /* pak vypocty */ A1 is A*N, /* aktualizace pomocne promenne - akumulatoru */ fact(N1,A1,F). /* a rekurzivni volani az na konec */- výpočet F jako 1*2*...*N
fact(N,F):-fact(1,N,1,F). fact(N,N,F,F). fact(I,N,C,F):-I<N, I1 is I+1, C1 is C*I, fact(I1,N1,C1,F).
^