ϵ">]>
3. CVIČENIE Z PREDMETU ÚVOD DO DEKLARATÍVNEHO PROGRAMOVANIA 2011/2012
ČASŤ B
http://ii.fmph.uniba.sk/cl/courses/1-AIN-505-udp/1112ls/ex/ex03.zip
Dátum: 27. 2. 2012
Odporúčaná verzia CL: 5.81.20
WWW stránka predmetu: http://dai.fmph.uniba.sk/courses/udp
Kontakt: udp(zavináč)lists.dai.fmph.uniba.sk
Úvodná poznámka. Toto cvičenie je venované priraďujúcim diskrimináciám (ex03a) a simulácii cyklov chvostovou rekurziou (ex03b).
Literatúra.
[1] J. Kľuka. Prednášky z Úvodu do deklaratívneho programovania LS 2011/2012.
http://ii.fmph.uniba.sk/cl/courses/1-AIN-505-udp/1112ls/udp-screen.pdf
[2] D. Guller. Poznámky k prednáškam z CL.
[3] J. Komara and P. J. Voda. Metamathematics of Computer Programming. 2001.
Poznámka. Podrobnejší návod na riešenie nasledujúcich úloh nájdete napríklad v prednáškach [1].
Úlohy označené hviezdičkou riešte po vyriešení všetkých neoznačených úloh.
Výpočet faktoriálu while cyklom. Funkciu
vypočítame pomocou pascalovského while cyklu nasledovne:
f := 1; } Fact while n <> 0 do begin - f := f*n; | n := n-1 |- While_fact end; | Result := f -
Úloha. Faktoriál simuláciou while cyklu. Simulujte uvedený while cyklus chvostovorekurzívnou funkciou a použite ju na zadefinovanie funkcie . Pomocný argument nazývame akumulátor.
Ako je naznačené vyššie, funkcia počíta iba cyklus a vrátenie výsledku.
Hlavná funkcia inicializuje akumulátor vhodným volaním funkcie .
Invariant:
Úloha. Umocnenie simuláciou while cyklu. Naprogramujte umocnenie pomocou simulácie while cyklu.
a) Do nasledujúcej poznámky vpíšte fragment pascalovského programu, ktorý vypočíta umocnenie do akumulátora , podobne ako pri faktoriáli.
b) Zadefinujte chvostovorekurzívnu funkciu , ktorá simuluje váš while cyklus, ale nie inicializáciu akumulátora.
Invariant:
Efektívny výpočet členov Fibonacciho postupnosti while cyklom. Funkciu pre -tý člen Fibonacciho postupnosti
môžeme efektívne vypočítať pomocou while cyklu s dvoma akumulátormi , , v ktorých si pamätáme dva po sebe nasledujúce členy postupnosti:
if n = 0 then - Result := 0 | else begin |_ Fib_efficient n := n - 1; { !! } | m := 0; { fib(0) } | d := 1; { fib(1) } - while n <> 0 do begin - { m = fib(i) & d = fib(i+1) } | m1 := d; | d1 := m+d; | m := m1; d := d1; |- While_fib { m = fib(i+1) & d = fib(i+2) } | n := n-1 | end; | Result := d - end
Úloha. Efektívny výpočet členov Fibonacciho postupnosti simuláciou while cyklu.
a) Simulujte while cyklus z predchádzajúcej poznámky chvostovorekurzívnu funkciou . Úvodný test a inicializáciu premenných zatiaľ neberte do úvahy.
Invariant:
b) Naprogramujte funkciu , ktorá vykoná úvodný test pascalovského programu a spustí simuláciu while cyklu so správne inicializovanými hodnotami premenných , , .
Úloha. Podobne ako v predchádzajúcej úlohe zadefinujte efektívnu verziu nasledujúcej funkcie simuláciou while cyklu.
a) Do nasledujúcej poznámky vpíšte pascalovský program, ktorý počíta funkciu while cyklom. Výpočet je podobný výpočtu Fibonacciho postupnosti. Program si pamätá 3 po sebe nasledujúce členy postupnosti v akumulátoroch , , .
if n = 0 then
...
else if n = 1 then
...
else begin
n := ...;
a := ...; { F1(0) }
b := ...; { F1(1) }
c := ...; { F1(2) }
while ... do begin
{ a = F1(i) & b = F1(i+1) & c = F1(i+2) }
...
{ a = F1(i+1) & b = F1(i+2) & c = F1(i+3) }
end;
Result := c
end
c) Vo funkcii ošetrite okrajové prípady a odštartujte cyklus so správne inicializovanými premennými.
Faktoriál simuláciou for cyklu. Faktoriál môžeme počítať aj pomocou pascalovského for cyklu:
f := 1; } Fact1 for i := 1 to n do begin - f := f*i |_ For_fact end; | Result := f -
Úloha. Faktoriál simuláciou for cyklu. Naprogramujte funkciu využitím pomocnej funkcie .
a) Funkcia simuluje for cyklus z predchádzajúcej poznámky. Zadefinujte ju spätnou rekuziou, pri ktorej rekurzívny argument rastie, kým neprekročí hranicu . Uvedomte si, že cyklus
for i := 1 to n do begin TELO end
je ekvivalentný
i := 1; while i <= n do begin TELO; i := i+1 end
Funkciu môžeme efektívne vypočítať nasledujúcim for cyklom.
if n = 0 then - Result := 0 | else if n = 1 then | Result := 1 |_ F2_efficient else begin | n := n - 2; { ! } | a := 0; { F2(0) } | b := 1; { F2(1) } - for i := 0 to n do begin - { a = F2(i) & b = F2(i+1) } | a1 := b; | b1 := a+b+i; |_ For_f2 a := a1; b := b1; | { a = F2(i+1) & c = F2(i+2) } | end; | Result := b - end
Simulujte for cyklus pomocnou chvostovorekurzívnou funkciou .
Invariant:
Úvodné testy, inicializáciu premenných a štart cyklu implementujte v hlavnej funkcii
Úloha. Zadefinujte efektívnu verziu funkcie simuláciou for cyklu podobne ako v predchádzajúcej úlohe.
Prémiová domáca úloha du03b. (2 body) Pravidlá pre prémiové domáce úlohy nájdete na http://dai.fmph.uniba.sk/courses/udp#pdu
Zistite presný počet rekurzívnych volaní potrebných na výpočet podľa klasickej neefektívnej definície (viď vyššie úvod k časti 7.2). Vysvetlite, ako ste k tomuto počtu dospeli.
[CL] Poznámka. Pri výpočte odpovede pomocou CL narazíte na nasledovný problém: Hľadaný počet rekurzívnych volaní je viac ako 30-bitové číslo. Takéto čísla CL normálne zobrazuje v zmiešanom desiatkovo-dyadickom zápise (vysvetlíme neskôr). V iba desiatkovej sústave číslo zobrazíte použitím formátu podľa nasledujúceho príkladu:
123456789*1000000001 = x:N