[[programovani-i|Programování I - cvičení]]
====== 4. cvičení - 2.10.2009 ======
===== Rekurze =====
Slovník o rekurzi praví (v jednom vtipu):
rekurze
Pokud ještě nevíš, co je to rekurze, viz heslo rekurze.
Rekurzivní funkce nebo procedura volá sama sebe. K řešení úlohy použije řešení úloh jednodušších. Úlohu rozloží na jednu nebo více částí, rekurzivně vyřeší jednodušší úlohy a z těchto jednodušších řešení složí řešení původní úlohy. Klíčové je, že úloha lze dostatečně zjednodušit, že má i nějaké triviální řešení, které není třeba řešit pomocí rekurze. Tedy rekurze nepostupuje neomezeně.
Speciálním případem je matematická indukce. Pro úlohu řádu N = 1 máme triviální řešení. Pro úlohu řádu N vyřešíme rekurzivně úlohu řádu N-1 a z toho zpracujeme řešení původní úlohy.
[[http://en.wikipedia.org/wiki/Recursion|Více o rekurzi na Wikipedii.]]
==== Triviální rekurze ====
* generování čísel 1..N bez použití cyklů (''for'', ''while'') nebo skoků (''goto'')
{ generate numbers 1 ... N }
procedure generate(i:integer);
begin
if (i > 1) then
generate(i-1);
writeln(i)
end;
var
n : integer;
begin
readln(n);
generate(n);
end.
==== Hanojské věže ====
* [[http://en.wikipedia.org/wiki/Tower_of_Hanoi|Hanojské věže]]
* [[http://mff.zamecnik.org/NPRG044-programovani-I/topfer/HANOJ.PAS|jiný zdroják]] - [[materialy|doc. Pavel Töpfer]]
program hanoi;
{
The Towers of Hanoi.
There are three bars and N discs of strictly increasing size.
The goal is to move all dics from bar 1 to bar 3 according to these rules:
* In each step only only disc can be moved.
* Only larger disc can be placed atop a smaller one.
The whole process should be made in the least possible number of steps.
Bohumir Zamecnik, 2009/01/22
}
procedure hanoiStep(n, barFrom, barTmp, barTo : integer);
begin
if (n = 1) then
begin
writeln(barFrom, ' -> ', barTo);
end
else if (n > 1) then
begin
hanoiStep(n - 1, barFrom, barTo, barTmp);
writeln(barFrom, ' -> ', barTo);
hanoiStep(n - 1, barTmp, barFrom, barTo);
end;
end;
var
nDiscs : integer;
begin
readln(nDiscs);
hanoiStep(nDiscs, 1, 2, 3);
end.
==== Variace ====
* generování variací s opakováním
program variace;
{ k-prvkove variace z n-prvkove mnoziny [0..n-1] s opakovanim }
const
MAX=10;
var
values : array [0..MAX] of integer;
n : integer;
procedure print;
var
i : integer;
begin
for i := 0 to n do
write(values[i], ' ');
writeln
end;
procedure generate(n, from : integer);
var
i : integer;
begin
for i := 0 to n do
begin
values[from] := i;
if (from < n) then
generate(n, from + 1)
else
print
end;
end;
begin
n := 4;
generate(n, 0);
end.
* generování variací bez opakování
program variace;
{ k-prvkove variace z n-prvkove mnoziny [0..n-1] bez opakovani }
const MAX=10;
var
values : array [0..MAX] of integer;
used : array [0..MAX] of boolean;
n,k : integer;
procedure print;
var
i : integer;
begin
for i := 0 to k do
write(values[i], ' ');
writeln
end;
procedure generate(from : integer);
var
i : integer;
begin
if (from > k) then
print
else
begin
for i := 0 to n do
begin
if (not used[i]) then
begin
used[i] := true;
values[from] := i;
generate(from + 1);
used[i] := false
end
end
end
end;
begin
readln(n, k);
dec(n);
dec(k);
init;
generate(0)
end.
==== Euklidův algoritmus ====
* rekurzivní verze [[http://en.wikipedia.org/wiki/Euclid_algorithm|Euklidova algoritmu]] z [[cviko1|1. cvika]]
program EuclidGCD;
{
Eukliduv algoritmus pro pocitani nejvetsiho spolecneho delitele dvou cisel
(znaci se NSD(a,b) nebo GCD(a,b).
}
var
a, b : longint;
{ Rekurzivni varianta, pouzito deleni se zbytkem (modulo) }
function GCD_rec(a:longint; b:longint) : longint;
begin
if b = 0 then
GCD_rec := a
else
GCD_rec := GCD_rec(b, a mod b)
end;
begin
writeln('Euclid algorithm for finding GCD of numbers A and B.');
repeat
write('A: ');
readln(a);
write('B: ');
readln(b);
writeln('GCD recursive using modulo: ', GCD_rec(a, b))
until ((a = 0) or (b = 0))
end.
===== Pokročilejší práce s Borland Pascalem =====
* debugování
* step over, trace into, breakpoint, watch, call stack