Rekurze. Pavel Töpfer, KSVI MFF UK Praha. 1. Co je to rekurze Rekurze v programech Rekurzivní algoritmy... 10

Rozměr: px
Začít zobrazení ze stránky:

Download "Rekurze. Pavel Töpfer, KSVI MFF UK Praha. 1. Co je to rekurze Rekurze v programech Rekurzivní algoritmy... 10"

Transkript

1 Rekurze Pavel Töpfer, KSVI MFF UK Praha OBSAH 1. Co je to rekurze Rekurze v programech Rekurzivní algoritmy Matematické rekurzivní vzorce Generování všech prvků dané vlastnosti Prohledávání s návratem Rozděl a panuj Rekurzivní datové struktury Efektivita rekurzivních postupů Zrychlení rekurze Nahrazení rekurzivních volání zásobníkem Odstranění rekurzivního postupu LITERATURA Tento text vychází ze stejnojmenné publikace vydané v roce 1998 nakladatelstvím Fortuna. Různé další rekurzivní algoritmy naleznete vedle tohoto textu také v učebnicích Pavel Töpfer: Algoritmy a programovací techniky, Prometheus Praha 1995, 2. vyd Niklaus Wirth: Algoritmy a štruktúry údajov, Alfa Bratislava 1988

2 1. Co je to rekurze Tento text podává základní přehled o tom, co je to rekurze a jak se v programování využívá. Obsahuje obecný výklad celé problematiky a řadu řešených úloh. Zabývá se vhodností a nevhodností použití rekurze v různých situacích a také otázkami efektivity rekurzivních algoritmů a programů. V programových ukázkách je zde všude používán programovací jazyk Pascal, resp. jeho implementace Turbo Pascal. Uvedené rekurzivní algoritmy jsou ale samozřejmě nezávislé na konkrétním programovacím jazyce. Algoritmus, datovou strukturu nebo třeba kresbu či jakýkoli jiný předpis označujeme jako rekurzivní, jestliže je definován pomocí sebe sama. Známý rekurzivní obrázek používaný v mnoha učebnicích o rekurzi znázorňuje televizor, na jehož obrazovce vidíme televizor, na jehož obrazovce vidíme televizor, atd. Tento jev jste ostatně mohli vidět na vlastní oči i ve skutečné televizi, pokud se v nějakém přenosu z televizního studia dostane náhodou do záběru televizní kamery obrazovka monitoru, v němž moderátoři sledují průběh vysílání. Popsaný rekurzivní jev je teoreticky nekonečný, ve skutečnosti však vidíme pouze jistý konečný počet obrazovek v sobě. Tato skutečnost je způsobena omezenou rozlišovací schopností jak televizní obrazovky, tak i tiskárny v případě tištěného obrázku. S některými rekurzivními jevy a postupy se setkáváme i jinde v životě. Snad každé malé dítě zná pohádku o kohoutkovi a slepičce. Lakomý kohoutek se nerozdělil se slepičkou o nalezený oříšek, spolknul ho sám a oříšek mu uváznul v krku. Slepička musí pro záchranu kohoutka podniknout složitou cestu. Potřebuje přinést kohoutkovi vodu ze studánky, ale studánka chce za vodu šátek od švadleny. Švadlena jí ale nedá šátek, dokud nedostane střevíce od ševce. A tak putování slepičky pokračuje stále dál. Kdykoli někoho o něco požádá, splnění její prosby je podmíněno dalším požadavkem. Ještě že po mnoha krocích svého putování narazí slepička na hodné nebe, které za rosu pro louku nic nechce. Počet rekurzivních kroků je tím pevně omezen a pohádka může šťastně skončit záchranou kohoutka. A kde že je v pohádce použita rekurze? Slepička opakovaně provádí akci typu přines od X předmět Y, která má rekurzivní charakter. K jejímu provedení je totiž nutné nejprve vykonat akci téhož typu, jen s jinými hodnotami X, Y. S podobným postupem se setkáváme i v dospělosti při jednání s různými úřady. Úřad A potřebuje k vystavení námi požadovaného dokladu nejprve donést potvrzení od úřadu B, úřad B ale žádá nejprve potvrzení od úřadu C, atd. Máme-li alespoň tolik štěstí jako pohádková slepička, narazíme po konečném počtu kroků na úřad, který od nás nic dalšího nepožaduje, a celou svoji záležitost můžeme nakonec úspěšně vyřídit. Uvedené příklady nám tedy zároveň ilustrují důležitost omezení hloubky rekurze pro praktickou použitelnost rekurzivního postupu. Různé rekurzivní předpisy se vyskytují zejména v matematice. Používají se například v definicích některých číselných posloupností. V pořadí n-tý člen posloupnosti {a n } může být zadán buď explicitním vzorcem v závislosti na n, např. a n =2n-1, nebo může být určen rekurzivně pomocí jiného nebo jiných členů téže posloupnosti, např. a n =a n Aby měla smysl takováto rekurzivní definice, musí být ovšem zadány ještě počáteční hodnoty, od kterých se celá rekurze odvíjí. V našem příkladu může tedy úplná definice posloupnosti {a n } vypadat třeba takto: a 1 = 1 a n = a n pro n > 1. Není stanovena žádná horní mez indexu n, takže v tomto případě máme rekurzivní předpis nekonečné číselné posloupnosti. Snadno zjistíte, že jde o posloupnost všech lichých celých čísel, 2

3 tedy o stejnou posloupnost, kterou jsme již dříve definovali také explicitním předpisem a n = 2n-1, n > 0. V případě posloupnosti lichých čísel bychom se bez rekurzivního předpisu klidně obešli, při výpočtech stejně raději použijeme jednoduchý explicitní vzorec. U některých posloupností však takovouto jednoduchou možnost nemáme. Buď explicitní vzorec vůbec neznáme, nebo je pro naše potřeby příliš komplikovaný. K nejznámějším posloupnostem, které bývá v matematice zvykem definovat rekurzivně, patří třeba faktoriál nebo posloupnost Fibonacciho čísel. Faktoriál celého kladného čísla n označujeme symbolem n!. Představuje součin všech kladných celých čísel od 1 do n. Faktoriál se používá ve velké míře například v kombinatorice. Formálně ho definujeme rekurzivním předpisem 1! = 1 n! = n.(n-1)! pro n > 1. Fibonacciho čísla patří k nejzajímavějším číselným posloupnostem. Setkáme se s nimi nejen v matematice, ale v různých nečekaných souvislostech i v biologii, ve výtvarném umění a také při návrhu algoritmů a programů. Posloupnost začíná dvěma jedničkami a dále pokračuje tak, že každé další Fibonacciho číslo je rovno součtu dvou bezprostředně předcházejících Fibonacciho čísel. Formálně tento rekurzivní vztah zapíšeme následovně: F 0 = 0 F 1 = 1 F n = F n-1 + F n-2 pro n > 1. Rekurzivní formule se objevují i v definicích některých geometrických útvarů a křivek. Nejznámější rekurzivně definované geometrické křivky patří mezi tzv. fraktální obrazce. Problematika fraktální geometrie je velmi bohatá a nemůžeme se jí zde podrobně věnovat. Ukážeme si proto alespoň dva typické příklady geometrických útvarů, jejichž definice jsou založeny na rekurzi. Prvním z nich bude slavná sněhová vločka Kochové. Při její konstrukci vyjdeme od rovnostranného trojúhelníka. Každou jeho stranu rozdělíme na třetiny a nad prostředním dílem každé strany sestrojíme menší rovnostranný trojúhelník (směrem ven od středu útvaru). Tím dostaneme křivku Kochové 2. řádu ve tvaru jednoduché pravidelné šesticípé hvězdy. Dále postupujeme stejným způsobem, tj. každou stranu vždy rozdělíme na třetiny a nad prostřední z nich sestrojíme rovnostranný trojúhelník směrem ven. Počet iterací není teoreticky nijak pevně omezen. Jako druhý příklad si můžeme uvést neméně známou Hilbertovu křivku. Hilbertova křivka 1. řádu je definována jednoduše pomocí tří spojených stejně dlouhých úseček. Hilbertovy křivky vyšších řádů jsou pak zadány rekurzivním předpisem. Křivku k-tého řádku pro k > 1 sestrojíme složením čtyř křivek řádu (k-1), které vůči sobě vhodně natočíme a spojíme třemi úsečkami. Názorně vidíme celou situaci na obrázku s prvními třemi Hilbertovými křivkami: 3

4 My se budeme v této knize zajímat o použití rekurze v programování. Rekurze se používá jak při návrhu algoritmů, tak i při realizaci algoritmů formou rekurzivních volání procedur a funkcí. Rekurzivní principy se uplatňují i při návrhu a používání některých datových struktur. Zaměříme se pouze na využití rekurze při práci s běžnými programovacími jazyky. Jejich typickým představitelem je Pascal, který budeme také používat ve všech programových ukázkách. Přesněji řečeno, budeme používat Turbo Pascal jakožto dnes nejrozšířenější implementaci Pascalu na PC. Nebudeme se věnovat ani neprocedurálním programovacím jazykům (jako jsou Lisp nebo Prolog), pro které je použití rekurze typické, ani jazykům speciálním (např. školní výukový jazyk Karel), které rovněž rekurzi bohatě využívají. Později se ještě vrátíme k některým příkladům uvedeným v této úvodní kapitole a ukážeme si možnosti jejich programové realizace. 4

5 2. Rekurze v programech Rekurze představuje velmi silný prostředek v rukou programátora. S využitím rekurze můžeme často napsat krátký a elegantní program, zatímco nerekurzivní řešení téhož problému by bylo mnohem pracnější. Použití rekurze má však také svá úskalí. Každý vysoce účinný nástroj se nám může stát nebezpečným, pokud s ním nepracujeme dostatečně opatrně a používáme ho neuváženě při práci, pro kterou není určen. Jestliže v programu použijeme rekurzi na nevhodném místě, můžeme dostat program, který bude sice funkčně správný, ale velmi nepřehledný a nesrozumitelný. V takovém programu se pak jen těžko provádějí nějaké pozdější úpravy nebo změny a je také pravděpodobnější, že se při zápisu programu dopustíme chyby. Hledání a odstraňování běhových chyb v rekurzivních programech bývá navíc obtížnější než v programech bez rekurze. Nešikovné použití rekurze nám však přináší ještě další nebezpečí. Často vede k programům, které jsou sice věcně správné, ale jsou příliš pomalé. V krajním případě se může snadno stát, že teoreticky dobře navržený program je prakticky nepoužitelný, neboť doba potřebná k jeho provedení na počítači přesahuje naše časové možnosti. Rekurzi bychom proto měli v programování používat vždy opatrně a pouze tam, kde je její použití účelné a přirozené, kde nám zjednoduší zápis programu a nezpůsobí přílišné zpomalení výpočtu. V programování se rekurze objevuje ve dvou odlišných rovinách. První z nich je rekurzivní návrh algoritmu, druhou pak použití rekurzivního volání procedury nebo funkce jakožto prostředku programovacího jazyka. Tyto dvě roviny spolu zpravidla úzce korespondují, rekurzivní volání využíváme zejména pro realizaci rekurzivních algoritmů. Nemusí tomu ale tak být vždycky. Algoritmus, který je svou povahou rekurzivní, můžeme naprogramovat i bez použití rekurzivních volání podprogramů tak, že mechanismus rekurzivního volání nahradíme vlastním programovým zásobníkem a cyklem v programu. Zápis programu se tím obvykle trochu zkomplikuje, výpočet ale bývá dokonce o něco rychlejší. Ušetří se totiž čas, který je při výpočtu rekurzivní verze programu potřebný pro vlastní režii rekurze, tj. pro každé zavolání rekurzivního podprogramu a pro jeho ukončení. Někdy rekurzivní volání procedur a funkcí ani použít nemůžeme, neboť zvolený programovací jazyk něco takového vůbec nepřipouští (např. původní verze jazyka Fortran). Naopak rekurzivní proceduru můžeme použít v programu i v situaci, kdy algoritmus žádnou rekurzi nevyžaduje. V krajním případě můžeme dokonce rekurzivní procedurou nahradit jakýkoli cyklus. Místo zápisu cyklu ve tvaru while P do S; je možné zavolat rekurzivní proceduru Q, kterou si předem deklarujeme takto: procedure Q; if P then S; Q Takovéto použití rekurze patří samozřejmě do kategorie těch naprosto nevhodných. Zápis programu zbytečně znepřehledňuje a navíc zpomaluje výpočet programu. Rekurze jakožto prvek programovacího jazyka spočívá v tom, že procedura nebo funkce může ve svém těle volat sama sebe. Tomuto volání pak říkáme rekurzivní volání procedury, resp. funkce. Je vykonáno stejným způsobem jako kterékoli jiné volání procedury. Mechanismus volání procedur a funkcí je v programovacích jazycích podobných Pascalu realizován pomocí vyhrazené oblasti operační paměti počítače zvané systémový zásobník. Při každém zavolání procedury (příp. funkce) se na vrcholu tohoto zásobníku vymezí místo pro tzv. aktivační záznam volané procedury. Ten obsahuje prostor pro uložení všech parametrů a lokálních proměnných procedury. Dále 5

6 obsahuje některé technické údaje, jako např. návratovou adresu (tj. adresu v kódu programu, odkud byla procedura zavolána). Tyto další údaje jsou potřebné pro správné provádění odkazů na globální proměnné během práce procedury a pro korektní ukončení procedury s předáním řízení zpět do místa jejího volání. V každém okamžiku výpočtu programu je na vrcholu systémového zásobníku umístěn aktivační záznam právě prováděné procedury. Při ukončení výpočtu této procedury je její aktivační záznam zrušen a výpočet programu pokračuje bezprostředně za příkazem volání právě skončené procedury. Každé zavolání rekurzivní procedury vede k vytvoření jejího nového aktivačního záznamu a tedy také ke vzniku nové, zcela samostatné sady jejích lokálních proměnných. Proměnné každého rozpočítaného exempláře rekurzivní procedury mají stejné identifikátory a stejnou strukturu, jsou však umístěny v paměti počítače na jiném místě a mohou proto mít odlišné hodnoty. Při rekurzivním volání se zaznamená místo, z něhož byl nový exemplář procedury zavolán, a příkazy procedury se pak začnou provádět znovu od začátku. Po ukončení výpočtu procedury se zruší její aktivační záznam umístěný na vrcholu zásobníku a provede se návrat do místa, odkud byla procedura zavolána. Tam se bude pokračovat v provádění příkazů staršího exempláře procedury, a to od zaznamenaného místa, kde předtím došlo k přerušení výpočtu. Přitom se bude používat původní sada proměnných s hodnotami, které v nich byly zanechány v okamžiku rekurzivního volání. Popsaný mechanismus rekurzivních volání si můžeme ukázat na rekurzivním tvaru funkce pro výpočet faktoriálu. Funkce nemá žádné lokální proměnné, ale má jeden parametr předávaný hodnotou. Parametr představuje kladné celé číslo, jehož faktoriál chceme spočítat. Zápis funkce přesně kopíruje rekurzivní definici faktoriálu uvedenou v úvodní kapitole: function Faktorial(N: integer): integer; if N = 1 then Faktorial := 1 else Faktorial := N * Faktorial(N-1) Jestliže v hlavním programu zavoláme funkci Faktorial s parametrem rovným 3, vytvoří se v systémovém zásobníku záznam s uloženým parametrem N=3 a funkce se začne provádět. Jelikož N je různé od 1, bude zavolána funkce Faktorial s parametrem hodnoty 2. Přitom se vytvoří druhý aktivační záznam s údajem N=2 a funkce Faktorial bude prováděna opět od začátku. Znovu je N různé od 1, a proto bude funkce Faktorial zavolána potřetí, tentokrát s parametrem 1. To vede k vytvoření třetího aktivačního záznamu na zásobníku s uloženou hodnotou N=1. Při zahájení výpočtu funkce Faktorial bude tentokrát splněna rovnost N = 1 a výpočet funkce proto ihned skončí s funkční hodnotou 1. Ze zásobníku se přitom odstraní vrchní záznam a výpočet pokračuje ve druhém exempláři funkce Faktorial, v němž N=2. Pokračuje se bezprostředně za místem právě ukončeného rekurzivního volání. Spočítá se funkční hodnota rovná 2 a výpočet funkce skončí. Přitom se ze zásobníku odstraní druhý aktivační záznam a řízení se vrátí do prvního, tedy nejstaršího exempláře funkce Faktorial, v jehož záznamu je uložen údaj N=3. Tam se spočítá funkční hodnota 3 * 2 = 6 a tato výsledná hodnota je předána hlavnímu programu. Zároveň s ukončením výpočtu funkce Faktorial je zrušen i její nejstarší aktivační záznam. Při psaní rekurzivních procedur a funkcí nesmíme nikdy zapomenout na ukončení rekurze. Každé rekurzivní volání musí být vázáno na splnění nějaké podmínky. Pokud by se v proceduře objevilo bezpodmínečné rekurzivní volání sama sebe, zavolání této procedury by vedlo nutně k nekonečnému výpočtu. Procedura by stále znovu a znovu volala sama sebe a žádné její volání by nebylo nikdy ukončeno. Vzhledem k tomu, že každé zavolání procedury nebo funkce je provázeno přidělením jistého paměťového prostoru v systémovém zásobníku a že pro celý zásobník je 6

7 vyhrazena předem pevně vymezená oblast v paměti počítače, výpočet takovéto procedury by po jisté době skončil běhovou chybou přeplnění systémového zásobníku. Procedura by totiž stále volala sama sebe a každé takovéto zavolání by si vyžadovalo vytvoření dalšího aktivačního záznamu v zásobníku, až by jednou došlo k úplnému zaplnění té části paměťového prostoru počítače, která je pro systémový zásobník vyhrazena. Tělo rekurzivní procedury proto zpravidla zahajujeme testem vhodně zvolené podmínky, která bývá vázána na hodnoty vstupních parametrů a která zajišťuje, že pro některé hodnoty již k dalšímu rekurzivnímu zavolání nedojde. Příklad takového testu vidíme ve funkci Faktorial a uvidíme ho ještě v mnoha dalších rekurzivních procedurách a funkcích. Vedle právě popsané tzv. přímé rekurze, kdy procedura nebo funkce volá ve svém těle sama sebe, existuje ještě rekurze nepřímá. Ta spočívá v tom, že je sice také v jednom okamžiku rozpočítáno více exemplářů téže procedury, nikoli však přímým zavoláním sama sebe. Procedura A může například volat proceduru B a procedura B zase proceduru A. Tento řetězec vzájemných volání procedur nebo funkcí může být i delší (např. A volá B, B volá C, C volá D, D volá A). Ze zběžného pohledu na zápis programu tudíž nemusí být ihned zřejmé, zda a ve kterém místě programu se vyskytuje rekurze. Chceme-li použít nepřímou rekurzi v programu zapsaném programovacím jazykem Pascal, musíme vhodně zvolit pořadí deklarací procedur, mezi nimiž se vztah nepřímé rekurze uplatňuje. V Pascalu totiž platí zásada, že každý identifikátor (tedy i identifikátor procedury) může být použit (tj. procedura může být zavolána) až za místem své deklarace. Vzájemnou závislost několika procedur můžeme řešit více způsoby. Zcela obecným a přehledným prostředkem pro deklaraci procedur či funkcí ve vztahu nepřímé rekurze je direktiva forward. V programu nejprve deklarujeme samotné hlavičky podprogramů včetně jejich parametrů, místo těl podprogramů však zapíšeme pouze klíčové slovo forward. Poté mohou již bez problémů následovat deklarace celých procedur a funkcí, a to dokonce v libovolném pořadí. Díky předsunuté deklaraci forward jsou při jejich překladu známa všechna jména podprogramů, které jsou z nich nepřímou rekurzí volány. Příklad: Mějme v programu tři procedury nazvané A, B, C ve vztahu nepřímé rekurze - procedura A volá proceduru B, ta volá proceduru C a procedura C volá proceduru A i proceduru B. Zápis deklarací těchto procedur může vypadat následovně: procedure A; forward; procedure B; forward; procedure C; forward; procedure A;... B;... procedure B;... C;... 7

8 procedure C;... A;... B;... Ne vždy je nutné zapisovat v programu předsunuté deklarace všech procedur, mezi nimiž se uplatňuje nepřímá rekurze. Je-li ve vztahu mezi procedurami pouze cyklická závislost, což je dosti častý případ, vystačíme s jedinou předsunutou deklarací a vhodně zvoleným pořadím zápisu procedur. Opět si to ukážeme na příkladu. Příklad: Mějme v programu tři procedury nazvané A, B, C ve vztahu nepřímé rekurze - procedura A volá proceduru B, ta volá proceduru C a procedura C volá proceduru A. Pořadí deklarací procedur může být následující: procedure A; forward; procedure C;... A;... procedure B;... C;... procedure A;... B;... Někdy se stává, že mezi rekurzivními procedurami je pouze cyklická závislost a navíc z vnějšku (např. z hlavního programu) je volána pouze jediná z těchto procedur. V takovém případě direktivu forward vůbec nepotřebujeme, stačí deklarovat všechny procedury ve vhodném pořadí jako lokální uvnitř té z nich, která je používána z vnějšku. Příklad: Mějme v programu tři procedury nazvané A, B, C ve vztahu nepřímé rekurze - procedura A volá proceduru B, ta volá proceduru C a procedura C volá proceduru A. Z hlavního programu je volána pouze procedura A. Soustavu těchto tří procedur můžeme deklarovat následovně: 8

9 procedure A; procedure C;... A; {smí volat, A je pro ni globální symbol}... procedure B;... C; {smí volat, C bylo deklarováno dříve}... {A}... B; {smí volat, B je její lokální procedura}... {A} S praktickým využitím nepřímé rekurze se v programech setkáváme o dost méně, než s rekurzí přímou. V této knize si předvedeme alespoň dva ukázkové programy založené na technice nepřímé rekurze. Půjde jednak o program na vykreslování Hilbertových křivek, o nichž jsme se již zmínili v úvodu, jednak o algoritmus vyhodnocování aritmetických výrazů. Oba tyto příklady užití nepřímé rekurze najdete hned v následující kapitole. 9

10 3. Rekurzivní algoritmy Pokusíme se nyní ukázat alespoň některé základní oblasti, kde se při návrhu algoritmů využívá rekurze a kde je její použití přirozené a výhodné. Jednotlivé rekurzivní postupy řešení úloh budeme demonstrovat na konkrétních příkladech. Nejprve si předvedeme algoritmy odvozené z různých matematických rekurzivních předpisů, dále rekurzivní řešení úloh typu nalézt všechny prvky jisté vlastnosti a s tím související algoritmy na prohledávání s návratem. Závěrečný oddíl této kapitoly je věnován rekurzivnímu postupu nazývanému rozděl a panuj. V následující čtvrté kapitole se seznámíme se základními rekurzivně definovanými datovými strukturami a také s algoritmy pro jejich zpracování Matematické rekurzivní vzorce Některé matematické objekty bývají definovány nebo popsány rekurzivními předpisy. Jako typický příklad nám poslouží třeba definice číselných posloupností, v nichž je n-tý člen posloupnosti a n popsán pomocí jednoho nebo více předcházejících členů. S několika konkrétními příklady takových posloupností jsme se již setkali v první kapitole, kde jsme uvedli rekurzivní definici posloupnosti lichých čísel, faktoriálu a Fibonacciho čísel. Při návrhu algoritmu pro výpočet n-tého členu rekurzivně definované posloupnosti máme dvě možnosti. Nejpohodlnější cestou bývá přímé přepsání rekurzivního předpisu do podoby rekurzivní funkce programovacího jazyka. To jsme si již ukázali v kap. 2 pro případ výpočtu faktoriálu. Z hlediska průběhu výpočtu bývá ale výhodnější postupovat jinak. Pokud se nám podaří odvodit z rekurzivní definice posloupnosti explicitní vzorec vyjadřující hodnotu členu a n pouze v závislosti na n, dostaneme rychlejší a mnohdy i paměťově méně náročný algoritmus. Buď se výpočet řádově zrychlí, nebo se alespoň odstraní zbytečná rekurzivní volání funkce, která sama o sobě vedou k dodatečným časovým i paměťovým nárokům vytvořeného programu. Jednoduchým příkladem demonstrujícím zrychlení výpočtu je již zmíněná posloupnost lichých čísel. Výpočet n-tého členu posloupnosti na základě rekurzivní definice a 1 = 1 a n = a n pro n > 1 má lineární časovou složitost, zatímco při použití explicitního vzorce a n = 2n - 1 pro n > 0 dosáhneme složitosti konstantní. Jako ukázka úspory zbytečných rekurzivních volání nám poslouží faktoriál. Explicitní vzorec n! = n pro n > 0 vede stejně jako rekurzivní definice faktoriálu k výpočtu s lineární časovou složitostí. Je však rychlejší o ušetřená rekurzivní volání funkce. function Faktorial(N: integer): integer; var I, F: integer; F := 1; for I:=2 to N do F := F * I; Faktorial := F 10

11 Rekurzivní jsou i některé geometrické předpisy. V kap. 1 jsme uvedli definici tzv. Hilbertovy křivky k-tého řádu, která je popsána složením čtyř křivek řádu o 1 nižšího. Ukážeme si nyní program pro grafické vykreslení Hilbertovy křivky daného řádu na obrazovce počítače. Program je založen na bezprostřední realizaci daného rekurzivního předpisu. Je zároveň hezkou ukázkou použití nepřímé rekurze. Různě natočené segmenty vytvářené křivky jsou vykreslovány samostatnými procedurami, které se podle potřeby navzájem volají. program Hilbert; {Vykreslení Hilbertovy křivky zvoleného řádu} uses Graph; var N: integer; {řád křivky} Gd, Gm: integer; {nastavení režimu grafické karty} Max: integer; {rozlišení grafické karty} H: integer; {velikost úsečky} Z: integer; {počet úseček na straně oblasti} I: integer; procedure UseckaDolu(H: integer); {kreslí úsečku směrem dolů délky H bodů} LineRel(0,H) procedure UseckaNahoru(H: integer); {kreslí úsečku směrem nahoru délky H bodů} LineRel(0,-H) procedure UseckaVlevo(H: integer); {kreslí úsečku směrem vlevo délky H bodů} LineRel(-H,0) procedure UseckaVpravo(H: integer); {kreslí úsečku směrem vpravo délky H bodů} LineRel(H,0) procedure ObloukDolu (Rad, H: integer); forward; procedure ObloukNahoru(Rad, H: integer); forward; procedure ObloukVlevo (Rad, H: integer); forward; procedure ObloukVpravo(Rad, H: integer); forward; procedure ObloukDolu(Rad, H: integer); {kreslí úsek H. křivky - oblouk dolů pravotočivý} {Rad - řád Hilbertovy křivky, H - velikost hrany} var R: integer; {o jeden řád méně} if Rad > 0 then 11

12 R := Rad - 1; ObloukVlevo(R,H); UseckaDolu(H); ObloukDolu(R,H); UseckaVlevo(H); ObloukDolu(R,H); UseckaNahoru(H); ObloukVpravo(R,H); {procedure ObloukDolu} procedure ObloukNahoru(Rad, H: integer); {kreslí úsek H. křivky - oblouk nahoru pravotočivý} {Rad - řád Hilbertovy křivky, H - velikost hrany} var R: integer; {o jeden řád méně} if Rad > 0 then R := Rad - 1; ObloukVpravo(R,H); UseckaNahoru(H); ObloukNahoru(R,H); UseckaVpravo(H); ObloukNahoru(R,H); UseckaDolu(H); ObloukVlevo(R,H); {procedure ObloukNahoru} procedure ObloukVlevo(Rad, H: integer); {kreslí úsek H. křivky - oblouk vlevo levotočivý} {Rad - řád Hilbertovy křivky, H - velikost hrany} var R: integer; {o jeden řád méně} if Rad > 0 then R := Rad - 1; ObloukDolu(R,H); UseckaVlevo(H); ObloukVlevo(R,H); UseckaDolu(H); ObloukVlevo(R,H); UseckaVpravo(H); ObloukNahoru(R,H); {procedure ObloukVlevo} procedure ObloukVpravo(Rad, H: integer); {kreslí úsek H. křivky - oblouk vpravo levotočivý} {Rad - řád Hilbertovy křivky, H - velikost hrany} var R: integer; {o jeden řád méně} if Rad > 0 then R := Rad - 1; 12

13 ObloukNahoru(R,H); UseckaVpravo(H); ObloukVpravo(R,H); UseckaNahoru(H); ObloukVpravo(R,H); UseckaVlevo(H); ObloukDolu(R,H); {procedure ObloukVpravo} write('řád Hilbertovy křivky: '); readln(n); Gd := Detect; Gm := Detect; InitGraph(Gd, Gm, ''); Max := GetMaxY; {počet bodů na obrazovce na výšku} {počet úseček na straně oblasti pro N-tý řád: 2^N-1} Z := 1; for I:=1 to N do Z := Z * 2; Z := Z - 1; {Z = počet úseček tvořících stranu} H := Max div Z; {délka jedné úsečky} MoveTo(Max,0); ObloukVlevo(N,H); readln; CloseGraph;. Jiným typickým postupem využívajícím vztahu nepřímé rekurze je jeden z algoritmů na vyhodnocení aritmetického výrazu. Budeme mít zadán aritmetický výraz, který bude pro jednoduchost tvořen pouze celočíselnými konstantami, binárními operátory +, -, *, / (znak / bude představovat celočíselné dělení) a kulatými závorkami s možností libovolného vnoření do sebe. Naším úkolem bude spočítat hodnotu tohoto výrazu. Pro řešení této úlohy existuje řada různých postupů (viz např. [5]). Jeden z nejlepších algoritmů s optimální lineární časovou složitostí je založen na rekurzivní definici aritmetického výrazu. Místo přesné formální definice si řekneme raději její hlavní myšlenky. Výraz je buď člen, nebo je to součet (příp. rozdíl) několika členů. Každý člen je buď faktor, nebo je to součin (příp. podíl) několika faktorů. Každý faktor je buď tvořen přímo celočíselnou konstantou, nebo je to výraz uzavřený v kulatých závorkách. V této definici je zachycen jak správný tvar zápisu výrazu, tak také postup správného vyhodnocování s ohledem na strukturu závorek a prioritu operátorů (násobení a dělení má vyšší prioritu než sčítání a odčítání). Algoritmus si ukážeme naprogramovaný v Turbo Pascalu ve tvaru funkce Vyhodnoceni. Funkce dostane ve svém parametru znakový řetězec obsahující vyhodnocovaný výraz a jako svou funkční hodnotu vrátí hodnotu tohoto výrazu. Funkce Vyraz, Clen a Faktor, které se navzájem volají metodou nepřímé rekurze, jsou lokálními funkcemi deklarovanými uvnitř funkce Vyhodnoceni. Jako jediný parametr typu řetězec si předávají tu část vyhodnocovaného výrazu, která ještě zbývá ke zpracování. Řetězec je zleva stále zkracován, až z něj zbude pouze jediný speciální znak $, který k původně zadanému výrazu připojuje z technických důvodů sama funkce Vyhodnoceni. program AritmetVyraz; {Vyhodnocení aritmetického výrazu soustavou procedur ve vztahu nepřímé rekurze podle formální gramatiky 13

14 popisující stavbu výrazu} var S: string; {uložení vyhodnocovaného výrazu} function Vyhodnoceni(S:string): integer; {funkce vyhodnocující aritmetický výraz} {metoda - nepřímá rekurze funkcí Vyraz, Clen, Faktor} {vyhodnocovaný výraz je zadán ve vstupním parametru S} {funkce předpokládá, že výraz je syntakticky správný} function Vyraz(var S: string): integer; forward; function Faktor(var S: string); integer; {pomocná funkce na vyhodnocení jednoho faktoru} {faktorem je číselná hodnota nebo výraz v závorkách} var H: integer; {číslo ve výrazu} Z: boolean; {znaménko minus u čísla} while S[1] = ' ' do Delete(S,1,1); if S[1] = '(' then Delete(S,1,1); {zrušit levou závorku} Faktor := Vyraz(S); while S[1] = ' ' do Delete(S,1,1); Delete(S,1,1); {zrušit pravou závorku} else {číselná konstanta} Z := false; if S[1] = '+' then Delete(S,1,1) else if S[1] = '-' then Delete(S,1,1); Z := true H := 0; while S[1] in ['0'..'9'] do H := H * 10 + ord(s[1]) - ord('0'); Delete(S,1,1) if Z then H := -H; Faktor := H {function Faktor} function Clen(var S: string): integer; {pomocná funkce na vyhodnocení jednoho členu} {členem je jeden faktor nebo součin/podíl více faktorů} var C: integer; {hodnota členu} C := Faktor(S); while S[1] = ' ' do Delete(S,1,1); while S[1] in ['*','/'] do if S[1] = '*' then {součin faktorů} 14

15 Delete(S,1,1); C := C * Faktor(S); while S[1] = ' ' do Delete(S,1,1); else if S[1] = '/' then {podíl faktorů} Delete(S,1,1); C := C div Faktor(S); while S[1] = ' ' do Delete(S,1,1); Clen := C {function Clen} function Vyraz(var S: string): integer; {funkce na vyhodnocení výrazu} {výraz je člen nebo součet/rozdíl členů} var V: integer; {hodnota výrazu} {function Vyraz} while S[1] = ' ' do Delete(S,1,1); V := Clen(S); while S[1] = ' ' do Delete(S,1,1); while S[1] in ['+','-'] do if S[1] = '+' then {součet členů} Delete(S,1,1); V := V + Clen(S); while S[1] = ' ' do Delete(S,1,1); else if S[1] = '-' then {rozdíl členů} Delete(S,1,1); V := V - Clen(S); while S[1] = ' ' do Delete(S,1,1); Vyraz := V {function Vyraz} {function Vyhodnoceni} S := S + '$'; {technický trik pro ukončení} Vyhodnoceni := Vyraz(S) {function Vyhodnoceni} write('vyhodnocovaný výraz: '); readln(s); writeln('hodnota výrazu: ', Vyhodnoceni(S)); readln. 15

16 3.2. Generování všech prvků dané vlastnosti Při řešení některých úloh je zapotřebí vygenerovat všechny prvky, k-tice, množiny či rozklady zadané vlastnosti. Úlohy tohoto typu musíme často řešit prostým zkoušením všech možností. Například při hledání všech k-tic celých čísel splňujících nějakou danou podmínku by však bylo nevýhodné a zbytečně pomalé vytvořit nejprve mechanicky všechny existující k-tice čísel a každou z nich pak dodatečně testovat, zda vyhovuje podmínce ze zadání úlohy. Lepší je vytvářet přímo pouze vyhovující k-tice. K tomu obvykle použijeme rekurzivní proceduru, která při svém prvním zavolání postupně umístí na první místo ve vytvářené k-tici všechna čísla, která se tam mohou objevit, a pro každý takovýto začátek zajistí dokončení celé k-tice pomocí rekurzivního volání sebe sama. Parametrem rekurzivního volání bude údaj, od kolikátého prvku je třeba pokračovat ve vytváření k-tice. Součástí algoritmu procedury musí být samozřejmě i podmínka pro ukončení rekurze. Jakmile bude ve vytvářené k-tici zvolena hodnota posledního, tj. k-tého prvku, procedura místo dalšího rekurzivního volání nalezenou k-tici předá jako výsledek (někam ji uloží nebo třeba přímo vytiskne). Celý postup si předvedeme na několika konkrétních úlohách. Začneme příklady z kombinatoriky. Následující programy slouží k vypsání všech k-prvkových kombinací bez opakování z N-prvkové množiny celých čísel {1, 2,..., N}, dále kombinací s opakováním, variací bez opakování a variací s opakováním. Připomeňme si ještě ve stručnosti význam těchto základních kombinatorických pojmů. K-prvkové kombinace z N prvků jsou všechny k-prvkové podmnožiny dané základní množiny {1, 2,..., N}, zatímco k-prvkové variace z N prvků jsou všechny uspořádané k-tice tvořené prvky této základní množiny. U variací tedy na rozdíl od kombinací záleží na pořadí prvků. Slova bez opakování a s opakováním udávají, zda se v kombinaci či variaci mohou některé prvky opakovat. Příklad: Všechny dvouprvkové kombinace, resp. variace, ze čtyř prvků vypadají následovně. kombinace bez opakování: {1,2} {1,3} {1,4} {2,3} {2,4} {3 4} kombinace s opakováním: {1,1} {1,2} {1,3} {1,4} {2,2} {2,3} {2,4} {3,3} {3 4} {4,4} variace bez opakování: (1,2) (1,3) (1,4) (2,1) (2,3) (2,4) (3,1) (3,2) (3,4) (4,1) (4,2) (4,3) variace s opakováním: (1,1) (1,2) (1,3) (1,4) (2,1) (2,2) (2,3) (2,4) (3,1) (3,2) (3,3) (3,4) (4,1) (4,2) (4,3) (4,4) program KombinaceBezOpakovani; {vypíše všechny K-prvkové kombinace bez opakování z N prvků (1,2,...,N) pro zadané hodnoty K, N} const MaxK = 20; {maximální přípustné K} var C: array[0..maxk] of byte; {uložení kombinace} N, K: byte; procedure Comb(p:byte); {p - pořadí vytvářeného prvku kombinace} {procedura používá globální proměnné C, K, N} {kombinace jsou vytvářeny s prvky vzestupně uspořádanými} var i:byte; if p > K then {hotovo} for i:= 1 to K do write(c[i]:3); writeln else {doplnit C[p]} 16

17 for i:=c[p-1]+1 to N-(K-p) do C[p] := i; Comb(p+1) write('výpočet K-prvkových kombinací bez opakování '); writeln('z N prvků'); write('zadejte hodnoty K a N: '); readln(k,n); C[0]:=0; {technický trik} Comb(1); readln;. program KombinaceSOpakovanim; {vypíše všechny K-prvkové kombinace s opakováním z N prvků (1,2,...,N) pro zadané hodnoty K, N} const MaxK = 20; {maximální přípustné K} var C: array[0..maxk] of byte; {uložení kombinace} N, K: byte; procedure Comb(p:byte); {p - pořadí vytvářeného prvku kombinace} {procedura používá globální proměnné C, K, N} {kombinace jsou vytvářeny s prvky vzestupně uspořádanými} var i:byte; if p > K then {hotovo} for i:= 1 to K do write(c[i]:3); writeln else {doplnit C[p]} for i:=c[p-1] to N do C[p] := i; Comb(p+1) write('výpočet K-prvkových kombinací s opakováním '); writeln('z N prvků'); write('zadejte hodnoty K a N: '); readln(k,n); C[0]:=1; {technický trik} Comb(1); readln;. 17

18 program VariaceBezOpakovani; {vypíše všechny K-prvkové variace bez opakování z N prvků (1,2,...,N) pro zadané hodnoty K, N} const MaxK = 20; {maximální přípustné K} var C: array[1..maxk] of byte; {uložení variace} N, K: byte; procedure Vari(p:byte); {p - pořadí vytvářeného prvku variace} {procedura používá globální proměnné C, K, N} var i, j: byte; nalez: boolean; if p > K then {hotovo} for i:= 1 to K do write(c[i]:3); writeln else {doplnit C[p]} for i:=1 to N do nalez := false; j:=1; while not nalez and (j < p) do if C[j] = i then nalez := true else j := j + 1 if not nalez then C[p] := i; Vari(p+1) write('výpočet K-prvkových variací bez opakování '); writeln('z N prvků'); write('zadejte hodnoty K a N: '); readln(k,n); Vari(1); readln;. program VariaceSOpakovanim; {vypíše všechny K-prvkové variace s opakováním z N prvků (1,2,...,N) pro zadané hodnoty K, N} const MaxK = 20; {maximální přípustné K} var C: array[1..maxk] of byte; {uložení variace} N, K: byte; procedure Vari(p:byte); {p - pořadí vytvářeného prvku variace} 18

19 {procedura používá globální proměnné C, K, N} var i, j: byte; if p > K then {hotovo} for i:= 1 to K do write(c[i]:3); writeln else {doplnit C[p]} for i:=1 to N do C[p] := i; Vari(p+1) write('výpočet K-prvkových variací s opakováním '); writeln('z N prvků'); write('zadejte hodnoty K a N: '); readln(k,n); Vari(1); readln;. Dalším základním kombinatorickým pojmem jsou permutace. Permutací N-prvkové množiny čísel {1, 2,..., N} rozumíme každé seřazení jejích prvků do uspořádané N-tice. Existuje přesně N! různých permutací dané N-prvkové množiny. Chceme-li je všechny vypsat, máme dvě základní možnosti, jak lze postupovat. První řešení je rekurzivní a vychází ze skutečnosti, že permutace N prvků jsou vlastně N-prvkové variace z daných N prvků bez opakování. Můžeme proto postupovat stejně jako při hledání variací. program Permutace_1; {vypíše všechny permutace N prvků (1,2,...,N) } {rekurzivní verze - postupné generování} (* uses Dos; *) const MaxN = 20; {maximální přípustné N} type Cisla = set of 1..MaxN; var A: array[1..maxn] of 1..MaxN; {uložení permutace} N: integer; {počet prvků} Pocet: integer; {počet permutací} (* procedure WriteTime; {Pomocná procedura pro výpis času} var H,M,S,S100: word; GetTime(H,M,S,S100); writeln('čas: ',H:4,M:4,S:4,S100:4) {procedure WriteTime} *) 19

20 procedure Perm(p: integer; S: Cisla); {p - pořadí vytvářeného prvku permutace} {S - čísla dosud nepoužitá v permutaci} {procedura používá globální proměnné A, N, Pocet} var i: integer; if p > N then {hotovo} for i:= 1 to N do write(a[i]:3); writeln; Pocet := Pocet + 1 else {doplnit A[p]} for i:=1 to N do if not (i in S) then A[p] := i; Perm(p+1, S+[i]) {procedure Perm} writeln('výpočet permutací N prvků'); write('zadejte hodnotu N: '); readln(n); Pocet := 0; (* WriteTime; *) Perm(1,[]); writeln('počet permutací: ', Pocet); (* WriteTime; *) readln;. Druhý, nerekurzivní postup řešení je o něco šikovnější a několikanásobně rychlejší. Místo postupného mechanického zkoušení všech možných rozložení prvků permutace pomocí rekurze budeme vytvářet přímo celé jednotlivé permutace, a to v tzv. lexikografickém uspořádání. Lexikografické uspořádání permutací je takové pořadí, které známe z řazení hesel ve slovníku. Ze dvou permutací stojí dříve ta, která má menší číslo na první pozici, v případě shody na první pozici rozhoduje menší číslo na druhém místě v permutaci zleva, atd. Například pro N=3 vypadá lexikografické uspořádání všech permutací takto: První v pořadí je permutace s prvky uspořádanými vzestupně, poslední permutace má prvky seřazené v sestupném pořadí. Algoritmus na vypsání všech permutací N prvků využívá proceduru, která ze zadané permutace N prvků vytvoří permutaci bezprostředně po ní následující v lexikografickém uspořádání. Začneme tedy od první permutace a touto procedurou ji budeme přetvářet tak dlouho, dokud nezískáme permutaci poslední. Zbývá vysvětlit, jak pracuje zmíněná procedura na nalezení bezprostředně následující permutace. Snaží se zvýšit zadanou permutaci, ale jen o co nejméně, jak je to možné. Změna se proto musí 20

21 odehrát v permutaci co nejvíce vpravo. Budeme tedy postupovat od pravého konce permutace a 1 a 2...a N směrem doleva a porovnávat dvojice sousedních prvků, tzn. postupně dvojice čísel (a N-1 a N ), (a N-2 a N-1 ), atd. Dokud je levý prvek takové dvojice větší než pravý, nemůžeme zatím pro zvýšení permutace nic udělat a postupujeme dál vlevo. Jakmile najdeme poprvé dvojici (a i a i+1 ), v níž a i <a i+1, průchod permutací zastavíme. Prvek a i je totiž konečně tím, který můžeme zvýšit. Hledáme nejbližší vyšší permutaci, a proto musíme a i nahradit nejbližším vyšším z prvků a i+1, a i+2,..., a N. Nechť je to a k. Zaměníme tedy v permutaci prvky a i, a k. Zbývá již jen uspořádat vzestupně prvky stojící vpravo od i-té pozice, aby vytvořená permutace s novou hodnotou a i byla co nejmenší. Nemusíme ale čísla pracně třídit, neboť víme, že platí a i+1 >a i+2 >...>a N-1 >a N. Na tomto uspořádání nic nepokazila ani výměna prvků a i, a k, neboť za a k bylo vybráno nejbližší vyšší číslo než bývalé a i. Stačí tedy jednoduše obrátit pořadí prvků a i+1, a i+2,..., a N a jsme hotovi. program Permutace_2; {vypíše všechny permutace N prvků (1,2,...,N) } {nerekurzivní verze - pomocí následníka v lexik. uspořádání} (* uses Dos; *) const MaxN = 20; {maximální přípustné N} type Pole = array[1..maxn] of 1..MaxN; var A: Pole; {uložení permutace} N: integer; {počet prvků} Pocet: integer; {počet permutací} i: integer; (* procedure WriteTime; {Pomocná procedura pro výpis času} var H,M,S,S100: word; GetTime(H,M,S,S100); writeln('čas: ',H:4,M:4,S:4,S100:4) {procedure WriteTime} *) function Dalsi (var P: Pole): boolean; {z permutace v poli P vytvoří nejbližší další v lexikografickém uspořádání} {vrací true, když se to podařilo vrací false, pokud P obsahovalo nejvyšší permutaci} {používá globální proměnné N, Pocet} var i, j, k, x: integer; i := N-1; while (i > 1) and (A[i] > A[i+1]) do i := i-1; if A[i] > A[i+1] then Dalsi := false else {číslo A[i] zvětšíme - nahradíme nejbližším vyšším číslem z úseku od A[i+1] do A[N]:} j := N; while A[j] < A[i] do j := j-1; 21

22 {vyměníme A[i] a A[j]:} x := A[i]; A[i] := A[j]; A[j] := x; {otočíme klesající úsek A[i+1]..A[N] na rostoucí:} j := i+1; k := N; while j < k do x := A[j]; A[j] := A[k]; A[k] := x; j := j+1; k := k-1; Dalsi := true {function Dalsi} writeln('výpočet permutací N prvků'); write('zadejte hodnotu N: '); readln(n); Pocet := 0; for i:=1 to N do A[i] := i; (* WriteTime; *) repeat for i:=1 to N do write(a[i]:3); writeln; Pocet := Pocet + 1 until not Dalsi(A); writeln('počet permutací: ', Pocet); (* WriteTime; *) readln;. Také v následujících příkladech půjde o vytváření všech skupin zadané vlastnosti. Mějme dáno N celých čísel bez znaménka, kde N není větší než 100. Dále je dáno celé číslo C. Naším úkolem je doplnit k zadaným číslům znaménka + nebo - tak, aby byl jejich součet roven číslu C. Chceme nalézt všechna přípustná řešení. Postup řešení je podobný jako u výše uvedených kombinatorických úloh. V jednom poli budeme mít pevně uložena sčítaná čísla, do druhého pole si budeme postupně ukládat jejich znaménka. Vytvoříme všechny možné N-tice za znamének + a - a pro každou z nich otestujeme odpovídající součet čísel. Sekvence znamének vytváříme rekurzivně. Jedno zavolání rekurzivní procedury má na starosti volbu znaménka u jednoho z čísel. Vyzkouší obě možnosti znaménka a pro každou z nich nechá prozkoumat všechna rozložení zbývajících znamének pomocí rekurzivního volání. Parametrem procedury je tudíž pořadové číslo umisťovaného znaménka. Ukončení rekurze je zajištěno kontrolou hodnoty tohoto parametru, zda nepřekročila N. Po vytvoření celé N-tice znamének je již možné projít pole čísel a znamének a zkontrolovat výsledný součet. Jinou stejně dobrou možností je předávat průběžný mezisoučet čísel s již stanovenými znaménky ve druhém parametru rekurzivní procedury. program Soucet_Cisel_V_Poli; {Je dáno N celých čísel a požadovaný součet C. Program doplní před každé z čísel znaménko + nebo - tak, aby byl součet takto upravených čísel roven danému C. Hledáme všechna možná řešení.} const MaxN = 100; {maximální počet čísel} 22

23 var H: array[1..maxn] of integer; {sčítaná čísla} N: integer; {počet čísel} C: integer; {hledaný součet} Z: array[1..maxn] of char; {uložení znamének} I: integer; procedure X (K:integer; Soucet:integer); {K - kolikáté znaménko hledáme, Soucet - průběžný součet čísel až do K-tého} {Procedura používá globální proměnné N, C, H, Z} var I:integer; if K = N+1 then {pole znamének zcela obsazeno} if Soucet = C then {našli jsme řešení} for I:=1 to N do write(z[i],h[i]); writeln else {zkusíme hodnoty K-tého znaménka} Z[K] := '+'; X(K+1, Soucet+H[K]); Z[K] := '-'; X(K+1, Soucet-H[K]); {procedure X} write('počet sčítaných čísel: '); readln(n); writeln('sčítaná čísla: '); for I:=1 to N do read(h[i]); write('požadovaný součet: '); readln(c); X(1, 0); {začínáme od prvního znaménka, dosud součet 0} readln;. V další úloze budeme studovat, jak mohou vypadat uzávorkování správně zapsaných aritmetických výrazů. Uvažujeme výraz obsahující N párů závorek. Z celého výrazu nás bude zajímat právě jen to, jaký tvar může mít struktura jeho závorek. Například pro N=3 existuje těchto pět možností: ((())) (()()) (())() ()(()) ()()() 23

24 Naším úkolem bude nalézt a vypsat všechna takováto správná uzávorkování výrazu pro zadaný počet párů závorek N. Úlohu budeme řešit opět pomocí rekurze. Posloupnosti závorek budeme vytvářet postupně zleva doprava. Procedura řešící úlohu převezme již vytvořenou úvodní část posloupnosti, prodlouží ji o jednu závorku a pak zajistí dokončení celé posloupnosti rekurzivním zavoláním sebe sama. Hloubka rekurze je omezena délkou vytvářené posloupnosti. Při každém rekurzivním zavolání je posloupnost prodloužena o jednu závorku, takže po provedení 2N volání v sobě může procedura místo dalšího rekurzivního volání přímo vypsat výsledek. Musíme se ale ještě vrátit ke slovům prodlouží ji o jednu závorku a zamyslet se, jakou závorku je možné k nějakému úvodnímu úseku posloupnosti přidat. V některých situacích je totiž možné přidat jedině levou závorku, v některých pouze pravou a v některých musíme vyzkoušet obě možnosti, chceme-li nalézt všechna přípustná řešení úlohy. Levou závorku můžeme připojit vždy, pokud úvodní úsek ještě neobsahuje N levých závorek. Pravou závorku lze použít tehdy, jestliže je co uzavírat, tzn. jestliže úvodní úsek obsahuje více levých závorek než pravých. Všechno ostatní je již jenom technickou záležitostí. Vytvářenou posloupnost závorek musíme podobně jako při řešení předchozí úlohy ukládat do pole. Toto pole musí být všemi exempláři procedury sdíleno, a proto ho budeme deklarovat jako globální (mohlo by stát také na místě parametru předávaného odkazem). Prostřednictvím vstupního parametru se musí procedura dozvědět, jak dlouhý úsek posloupnosti je již vytvořen a uložen v poli. Přímo v poli by pak bylo možné spočítat, kolik je v tomto úseku levých a kolik pravých závorek. Šikovnější je však zavést parametry jinak a přímo v parametrech předávat proceduře informaci, kolik levých a kolik pravých závorek úvodní úsek obsahuje. Ušetříme tím práci spojenou s opakovaným procházením pole při každém zavolání procedury. program Uzavorkovani; {Vygeneruje všechna správná uzávorkování výrazu pomocí N párů kulatých závorek} const MaxN = 100; {maximální přípustné N} var Z: array[1..maxn*2] of char; {uložení závorek} N: integer; {počet párů závorek} I: integer; procedure Zavorky(L, P: integer); {L, P - kolik jsme už umístili levých a pravých závorek} {používá globální proměnnou N} if L < N then {můžeme dát levou} Z[L+P+1] := '('; Zavorky(L+1,P) if P < L then {můžeme dát pravou} Z[L+P+1] := ')'; Zavorky(L,P+1) if P = N then {uzávorkování vytvořeno} for I:=1 to 2*N do write(z[i]); writeln {procedure Zavorky} 24

25 write('počet párů závorek: '); readln(n); Zavorky(0,0); readln;. Další ukázková úloha pojednává o placení. Úkolem je nalézt všechny způsoby, jimiž je možné zaplatit danou částku pomocí dané sady platidel. Předpokládáme, že od každé hodnoty platidla máme v zásobě dostatečný počet kusů. Úlohu si nejlépe přiblížíme na konkrétním příkladu. Budeme uvažovat platidla o hodnotách 1 Kč, 2 Kč, 5 Kč, 10 Kč, 20 Kč a 50 Kč. Částku 12 Kč můžeme zaplatit těmito patnácti způsoby: 1 x 10 Kč + 1 x 2 Kč 1 x 10 Kč + 2 x 1 Kč 2 x 5 Kč + 1 x 2 Kč 2 x 5 Kč + 2 x 1 Kč 1 x 5 Kč + 3 x 2 Kč + 1 x 1 Kč 1 x 5 Kč + 2 x 2 Kč + 3 x 1 Kč 1 x 5 Kč + 1 x 2 Kč + 5 x 1 Kč 1 x 5 Kč + 7 x 1 Kč 6 x 2 Kč 5 x 2 Kč + 2 x 1 Kč 4 x 2 Kč + 4 x 1 Kč 3 x 2 Kč + 6 x 1 Kč 2 x 2 Kč + 8 x 1 Kč 1 x 2 Kč + 10 x 1 Kč 12 x 1 Kč Úlohu je možné řešit různými způsoby. Budeme-li uvažovat pouze pevnou sadu platidel nebo alespoň sadu platidel o předem známém počtu různých hodnot, můžeme napsat řešení založené na příslušném počtu cyklů vnořených do sebe. Pokud pracujeme s N platidly, vystačíme s N-1 cykly. Víme-li navíc, že je mezi platidly vždy jednokoruna, takže libovolnou celou částku bude možné zaplatit, budeme v těchto cyklech zkoumat všechny přípustné počty vyšších platidel, uvnitř cyklů pak doplatíme zbytek částky jednokorunami a vytiskneme výsledek. Pokud by nebylo zaručeno, že jednokoruna bude v sadě platidel obsažena, museli bychom do vnitřního cyklu doplnit navíc jeden test pro kontrolu, zda má úloha řešení. program Platidla_1; {Zaplatit danou částku všemi způsoby danou sadou platidel. Nerekurzivní verze s pevným počtem platidel. První hodnotou platidla je vždy 1, dalších pět hodnot platidel je zadáno na vstupu.} var H1, H2, H3, H4, H5, H6: integer; {hodnoty platidel} P1, P2, P3, P4, P5, P6: integer; {počty platidel} 25

26 Z1, Z2, Z3, Z4, Z5, Z6: integer; {zbývá zaplatit} Zapl: integer; {počet různých zaplacení} writeln('nejmenší platidlo hodnoty 1 se nezadává'); H1 := 1; write('hodnoty dalších 5 platidel: '); readln(h2, H3, H4, H5, H6); write('částka k zaplacení: '); readln(z6); Zapl := 0; for P6:=0 to Z6 div H6 do Z5 := Z6 - P6 * H6; for P5:=0 to Z5 div H5 do Z4 := Z5 - P5 * H5; for P4:=0 to Z4 div H4 do Z3 := Z4 - P4 * H4; for P3:=0 to Z3 div H3 do Z2 := Z3 - P3 * H3; for P2:=0 to Z2 div H2 do Z1 := Z2 - P2 * H2; P1 := Z1; {neboť H1 = 1} write(p1,' x ',H1,' + ',P2,' x ',H2,' + '); write(p3,' x ',H3,' + ',P4,' x ',H4,' + '); writeln(p5,' x ',H5,' + ',P6,' x ',H6); Zapl := Zapl + 1; writeln('počet možných zaplacení: ', Zapl); readln;. Právě popsané řešení s velkým množstvím cyklů vnořených do sebe není zrovna nejelegantnější. Nemůžeme ho navíc použít v případě, je-li úloha zadána zcela obecně a předem neznáme počet druhů platidel, s nimiž je třeba pracovat. V této situaci nám opět pomůže rekurze. Každé zavolání procedury bude odpovídat jednomu z platidel, hloubka rekurze bude tedy omezena počtem platidel. Procedura vyzkouší v cyklu všechny vhodné počty toho platidla, které má na starosti, a pro každý z těchto počtů zajistí doplacení zbývající částky dalšími platidly pomocí rekurzivního volání. Údaje o počtech platidel jednotlivých druhů v právě vytvářeném rozkladu se budou opět ukládat do globálního pole. Parametry procedury budou pořadové číslo právě zkoumaného platidla a částka, která ještě zbývá k zaplacení. Ukážeme si dvě varianty řešení. První z nich je jednodušší a předpokládá, že každá použitá sada platidel obsahuje jednokorunu. Druhé řešení je zcela obecné. program Platidla_2; 26

27 {Zaplatit danou částku všemi způsoby danou sadou platidel. Rekurzivní verze s obecným počtem platidel. První hodnotou platidla je vždy 1, další platidla jsou dána na vstupu.} const Max = 100; {maximální počet platidel} var H: array[1..max] of integer; {hodnoty platidel} P: array[1..max] of integer; {počty platidel} N: integer; {počet platidel} Castka: integer; {částka k zaplacení} Zapl: integer; {počet různých zaplacení} i: integer; procedure Plat(J, Z: integer); {J - index právě používaného platidla Z- zbývá ještě zaplatit} {používá globální proměnné H, P, N} var i: integer; if J = 1 then P[1] := Z; {neboť H[1]=1} for i:=1 to N-1 do write(p[i],' x ',H[i],' + '); writeln(p[n],' x ',H[N]); Zapl := Zapl + 1; else for i:=0 to Z div H[J] do {i = počet použitých platidel indexu J} P[J] := i; Plat(J-1, Z-i*H[J]) {procedure Plat} write('počet platidel: '); readln(n); writeln('nejmenší platidlo hodnoty 1 se nezadává'); H[1] := 1; write('hodnoty dalších ', N-1, ' platidel: '); for i:=2 to N do read(h[i]); write('částka k zaplacení: '); readln(castka); Zapl := 0; Plat(N, Castka); writeln('počet možných zaplacení: ', Zapl); readln;. program Platidla_3; {Zaplatit danou částku všemi způsoby danou sadou platidel. Rekurzivní verze s obecným počtem platidel. Sada platidel nemusí obsahovat platidlo s hodnotou 1.} const Max = 100; {maximální počet platidel} var H: array[1..max] of integer; {hodnoty platidel} 27

Rekurze. Pavel Töpfer, 2017 Programování 1-8 1

Rekurze. Pavel Töpfer, 2017 Programování 1-8 1 Rekurze V programování ve dvou hladinách: - rekurzivní algoritmus (řešení úlohy je definováno pomocí řešení podúloh stejného charakteru) - rekurzivní volání procedury nebo funkce (volá sama sebe přímo

Více

Programovací jazyk Pascal

Programovací jazyk Pascal Programovací jazyk Pascal Syntaktická pravidla (syntaxe jazyka) přesná pravidla pro zápis příkazů Sémantická pravidla (sémantika jazyka) pravidla, která každému příkazu přiřadí přesný význam Všechny konstrukce

Více

Binární soubory (datové, typované)

Binární soubory (datové, typované) Binární soubory (datové, typované) - na rozdíl od textových souborů data uložena binárně (ve vnitřním tvaru jako v proměnných programu) není čitelné pro člověka - všechny záznamy téhož typu (může být i

Více

Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem

Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem Test prvočíselnosti Úkol: otestovat dané číslo N, zda je prvočíslem 1. zkusit všechny dělitele od 2 do N-1 časová složitost O(N) cca N testů 2. stačí zkoušet všechny dělitele od 2 do N/2 (větší dělitel

Více

Prohledávání do šířky = algoritmus vlny

Prohledávání do šířky = algoritmus vlny Prohledávání do šířky = algoritmus vlny - souběžně zkoušet všechny možné varianty pokračování výpočtu, dokud nenajdeme řešení úlohy průchod stromem všech možných cest výpočtu do šířky, po vrstvách (v každé

Více

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky Vyučovací hodina 1vyučovací hodina: Opakování z minulé hodiny Nová látka Procvičení nové látky Shrnutí 5 min 20 min 15 min 5 min 2vyučovací hodiny: Opakování z minulé hodiny Nová látka Procvičení nové

Více

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7 Pascal Katedra aplikované kybernetiky Ing. Miroslav Vavroušek Verze 7 Proměnné Proměnná uchovává nějakou informaci potřebnou pro práci programu. Má ve svém oboru platnosti unikátní jméno. (Připadne, musí

Více

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu: Čtvrtek 8 prosince Pascal - opakování základů Struktura programu: 1 hlavička obsahuje název programu, použité programové jednotky (knihovny), definice konstant, deklarace proměnných, všechny použité procedury

Více

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C Hanojské věže - 3 kolíky A, B, C - na A je N disků různé velikosti, seřazené od největšího (dole) k nejmenšímu (nahoře) - kolíky B a C jsou prázdné - úkol: přenést všechny disky z A na B, mohou se odkládat

Více

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik;

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik; Vícerozměrné pole type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik; M[2,3] := 3145; - počet indexů není omezen (v praxi obvykle nejvýše tři) - více indexů pomalejší přístup k prvku (počítá

Více

dovolují dělení velkých úloh na menší = dekompozice

dovolují dělení velkých úloh na menší = dekompozice Podprogramy dovolují dělení velkých úloh na menší = dekompozice Příklad: Vytiskněte tabulku malé násobilky ve tvaru XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X X 1 2 3 4 5 6 7 8 9 10 X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Více

Rekurze. Jan Hnilica Počítačové modelování 12

Rekurze. Jan Hnilica Počítačové modelování 12 Rekurze Jan Hnilica Počítačové modelování 12 1 Rekurzivní charakter úlohy Výpočet faktoriálu faktoriál : n! = n (n - 1) (n - 2)... 2 1 (0! je definován jako 1) můžeme si všimnout, že výpočet n! obsahuje

Více

1 PRVOCISLA: KRATKY UKAZKOVY PRIKLAD NA DEMONSTRACI BALIKU WEB 1

1 PRVOCISLA: KRATKY UKAZKOVY PRIKLAD NA DEMONSTRACI BALIKU WEB 1 1 PRVOCISLA: KRATKY UKAZKOVY PRIKLAD NA DEMONSTRACI BALIKU WEB 1 1. Prvocisla: Kratky ukazkovy priklad na demonstraci baliku WEB. Nasledujici program slouzi pouze jako ukazka nekterych moznosti a sluzeb,

Více

6 Příkazy řízení toku

6 Příkazy řízení toku 6 Příkazy řízení toku Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost příkazům pro řízení toku programu. Pro všechny tyto základní

Více

NPRG030 Programování I, 2015/16 1 / :25:32

NPRG030 Programování I, 2015/16 1 / :25:32 NPRG030 Programování I, 2015/16 1 / 21 22. 10. 2015 13:25:32 Podprogramy Příklad: Vytiskněte tabulku malé násobilky ve tvaru XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X X 1 2 3 4 5 6 7 8 9 10 X

Více

Programovací jazyk. - norma PASCAL (1974) - implementace Turbo Pascal, Borland Pascal FreePascal Object Pascal (Delphi)

Programovací jazyk. - norma PASCAL (1974) - implementace Turbo Pascal, Borland Pascal FreePascal Object Pascal (Delphi) Programovací jazyk - norma PASCAL (1974) - implementace Turbo Pascal, Borland Pascal FreePascal Object Pascal (Delphi) Odlišnosti implementace od normy - odchylky např.: nepovinná hlavička programu odlišná

Více

Obecná informatika. Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. Podzim 2012

Obecná informatika. Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. Podzim 2012 Obecná informatika Přednášející Putovních přednášek Matematicko-fyzikální fakulta Univerzity Karlovy v Praze Podzim 2012 Přednášející Putovních přednášek (MFF UK) Obecná informatika Podzim 2012 1 / 18

Více

1.1 Struktura programu v Pascalu Vstup a výstup Operátory a některé matematické funkce 5

1.1 Struktura programu v Pascalu Vstup a výstup Operátory a některé matematické funkce 5 Obsah Obsah 1 Programovací jazyk Pascal 1 1.1 Struktura programu v Pascalu.................... 1 2 Proměnné 2 2.1 Vstup a výstup............................ 3 3 Operátory a některé matematické funkce 5

Více

Časová a prostorová složitost algoritmů

Časová a prostorová složitost algoritmů .. Časová a prostorová složitost algoritmů Programovací techniky doc. Ing. Jiří Rybička, Dr. ústav informatiky PEF MENDELU v Brně rybicka@mendelu.cz Hodnocení algoritmů Programovací techniky Časová a prostorová

Více

Jednoduché cykly 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.

Jednoduché cykly 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. Jednoduché cykly Tento oddíl obsahuje úlohy na první procvičení práce s cykly. Při řešení každé ze zde uvedených úloh stačí použít vedle podmíněných příkazů jen jediný cyklus. Nepotřebujeme používat ani

Více

Anotace. Jednotky (tvorba a využití), struktury (typ record),

Anotace. Jednotky (tvorba a využití), struktury (typ record), Anotace Jednotky (tvorba a využití), struktury (typ record), medián v lineárním čase. Jednotky oddělený překlad Občas máme obecně využitelné funkce, které chceme používat v různých programech současně.

Více

ALGORITMIZACE A PROGRAMOVÁNÍ

ALGORITMIZACE A PROGRAMOVÁNÍ Metodický list č. 1 Algoritmus a jeho implementace počítačovým programem Základním cílem tohoto tematického celku je vysvětlení pojmů algoritmus a programová implementace algoritmu. Dále je cílem seznámení

Více

Implementace LL(1) překladů

Implementace LL(1) překladů Překladače, přednáška č. 6 Ústav informatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Poslední aktualizace: 30. října 2007 Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku

Více

(Úlohy z MO kategorie P, 32. část)

(Úlohy z MO kategorie P, 32. část) Rozklady na součet (Úlohy z MO kategorie P, 32. část) PAVEL TÖPFER Matematicko-fyzikální fakulta UK, Praha Náš dlouhodobý seriál o úlohách z Matematické olympiády kategorie P se dnes zastaví ve 39. ročníku

Více

1. D Y N A M I C K É DAT O V É STRUKTUR Y

1. D Y N A M I C K É DAT O V É STRUKTUR Y 1. D Y N A M I C K É DAT O V É STRUKTUR Y Autor: Petr Mik Abychom se mohli pustit do dynamických datových struktur, musíme se nejdřív podívat na datový typ ukazatel. 1. D AT O V Ý TYP U K A Z AT E L Datové

Více

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz (2 + 5) * (13-4) * + - 2 5 13 4 - listy stromu obsahují operandy (čísla) - vnitřní uzly obsahují operátory (znaménka)

Více

VÝUKOVÝ MATERIÁL. Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632 Číslo projektu

VÝUKOVÝ MATERIÁL. Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632 Číslo projektu VÝUKOVÝ MATERIÁL Identifikační údaje školy Vyšší odborná škola a Střední škola, Varnsdorf, příspěvková organizace Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632

Více

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010 Dynamické programování Jiří Vyskočil, Marko Genyg-Berezovskyj 2010 Rozděl a panuj (divide-and-conquer) Rozděl (Divide): Rozděl problém na několik podproblémů tak, aby tyto podproblémy odpovídaly původnímu

Více

Příklady: (y + (sin(2*x) + 1)*2)/ /2 * 5 = 8.5 (1+3)/2 * 5 = /(2 * 5) = 1.3. Pavel Töpfer, 2017 Programování 1-3 1

Příklady: (y + (sin(2*x) + 1)*2)/ /2 * 5 = 8.5 (1+3)/2 * 5 = /(2 * 5) = 1.3. Pavel Töpfer, 2017 Programování 1-3 1 Výraz - syntaxe i sémantika podobné jako v matematice - obsahuje proměnné, konstanty, operátory, závorky, volání funkcí - všechny operátory nutno zapisovat (nelze např. vynechat znak násobení) - argumenty

Více

5 Rekurze a zásobník. Rekurzivní volání metody

5 Rekurze a zásobník. Rekurzivní volání metody 5 Rekurze a zásobník Při volání metody z metody main() se do zásobníku uloží aktivační záznam obsahující - parametry - návratovou adresu, tedy adresu, kde bude program pokračovat v metodě main () po skončení

Více

Úvod do programování

Úvod do programování Úvod do programování Základní literatura Töpfer, P.: Algoritmy a programovací techniky, Prometheus, Praha učebnice algoritmů, nikoli jazyka pokrývá velkou část probíraných algoritmů Satrapa, P.: Pascal

Více

Vektory a matice. Obsah. Aplikovaná matematika I. Carl Friedrich Gauss. Základní pojmy a operace

Vektory a matice. Obsah. Aplikovaná matematika I. Carl Friedrich Gauss. Základní pojmy a operace Vektory a matice Aplikovaná matematika I Dana Říhová Mendelu Brno Obsah 1 Vektory Základní pojmy a operace Lineární závislost a nezávislost vektorů 2 Matice Základní pojmy, druhy matic Operace s maticemi

Více

Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují

Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují 1. u + v = v + u, u, v V 2. (u + v) + w = u + (v + w),

Více

MAXScript výukový kurz

MAXScript výukový kurz MAXScript výukový kurz Díl čtvrtý jazyk MAXScript, část I. Jan Melichar, březen 2008 Jan Melichar (aka JME) strana 1 OBSAH ÚVOD... 4 ZÁKLADNÍ PŘÍKAZY... 5 OPERÁTORY... 6 PROMĚNNÉ... 6 POLE... 7 ZÁVĚREM...

Více

Program a životní cyklus programu

Program a životní cyklus programu Program a životní cyklus programu Program algoritmus zapsaný formálně, srozumitelně pro počítač program se skládá z elementárních kroků Elementární kroky mohou být: instrukce operačního kódu počítače příkazy

Více

5 Orientované grafy, Toky v sítích

5 Orientované grafy, Toky v sítích Petr Hliněný, FI MU Brno, 205 / 9 FI: IB000: Toky v sítích 5 Orientované grafy, Toky v sítích Nyní se budeme zabývat typem sít ových úloh, ve kterých není podstatná délka hran a spojení, nýbž jejich propustnost

Více

Maturitní otázky z předmětu PROGRAMOVÁNÍ

Maturitní otázky z předmětu PROGRAMOVÁNÍ Wichterlovo gymnázium, Ostrava-Poruba, příspěvková organizace Maturitní otázky z předmětu PROGRAMOVÁNÍ 1. Algoritmus a jeho vlastnosti algoritmus a jeho vlastnosti, formy zápisu algoritmu ověřování správnosti

Více

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21. Vyhledávání doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava Prezentace ke dni 21. září 2018 Jiří Dvorský (VŠB TUO) Vyhledávání 242 / 433 Osnova přednášky

Více

- znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku

- znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku Znaky - standardní typ char var Z, W: char; - znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku - v TP (často i jinde) se používá kódová

Více

NPRG030 Programování I, 2017/18 1 / :22:16

NPRG030 Programování I, 2017/18 1 / :22:16 NPRG030 Programování I, 2017/18 1 / 26 20. 10. 2017 11:22:16 Ordinální typy standardní: integer, char, boolean Vlastnosti ordinálních typů: 1. hodnot je konečný počet a hodnoty jsou uspořádány 2. ke každé

Více

Algoritmizace a programování

Algoritmizace a programování Algoritmizace a programování Výrazy Operátory Výrazy Verze pro akademický rok 2012/2013 1 Operace, operátory Unární jeden operand, operátor se zapisuje ve většině případů před operand, v některých případech

Více

1. Implementace funkce počet vrcholů. Předmět: Algoritmizace praktické aplikace (3ALGA)

1. Implementace funkce počet vrcholů. Předmět: Algoritmizace praktické aplikace (3ALGA) Předmět: Algoritmizace praktické aplikace (3ALGA) Vytvořil: Jan Brzeska Zadání: Vytvoření funkcí na stromech (reprezentace stromu směrníky). Zadané funkce: 1. Počet vrcholů 2. Počet listů 3. Součet 4.

Více

Cykly a pole 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116.

Cykly a pole 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. Cykly a pole Tato část sbírky je tvořena dalšími úlohami na práci s cykly. Na rozdíl od předchozího oddílu se zde již v řešeních úloh objevuje více cyklů, ať už prováděných po sobě nebo vnořených do sebe.

Více

Sada 1 - Základy programování

Sada 1 - Základy programování S třední škola stavební Jihlava Sada 1 - Základy programování 13. Práce s řetězci - palindrom Digitální učební materiál projektu: SŠS Jihlava šablony registrační číslo projektu:cz.1.09/1.5.00/34.0284 Šablona:

Více

Dynamické programování

Dynamické programování Dynamické programování prof. Ing. Pavel Tvrdík CSc. Katedra počítačových systémů Fakulta informačních technologií České vysoké učení technické v Praze c Pavel Tvrdík, 2010 Efektivní algoritmy (BI-EFA)

Více

Logo2 operace, rekurze, větvení výpočtu

Logo2 operace, rekurze, větvení výpočtu Operace Logo2 operace, rekurze, větvení výpočtu Je naše vlastní operace, jejím výsledkem je nějaká hodnota. Na určení tohoto výsledku musíme použít základní příkaz jazyka Imagine logo. A tím je výsledek.

Více

Je n O(n 2 )? Je n 2 O(n)? Je 3n 5 +2n Θ(n 5 )? Je n 1000 O(2 n )? Je 2 n O(n 2000 )? Cvičení s kartami aneb jak rychle roste exponenciála.

Je n O(n 2 )? Je n 2 O(n)? Je 3n 5 +2n Θ(n 5 )? Je n 1000 O(2 n )? Je 2 n O(n 2000 )? Cvičení s kartami aneb jak rychle roste exponenciála. Příklady: Je n O(n 2 )? Je n 2 O(n)? Je 3n 5 +2n 3 +1000 Θ(n 5 )? Je n 1000 O(2 n )? Je 2 n O(n 2000 )? Cvičení s kartami aneb jak rychle roste exponenciála. Další pojmy složitosti Složitost v nejlepším

Více

1 Řešení soustav lineárních rovnic

1 Řešení soustav lineárních rovnic 1 Řešení soustav lineárních rovnic 1.1 Lineární rovnice Lineární rovnicí o n neznámých x 1,x 2,..., x n s reálnými koeficienty rozumíme rovnici ve tvaru a 1 x 1 + a 2 x 2 +... + a n x n = b, (1) kde koeficienty

Více

9 Kolmost vektorových podprostorů

9 Kolmost vektorových podprostorů 9 Kolmost vektorových podprostorů Od kolmosti dvou vektorů nyní přejdeme ke kolmosti dvou vektorových podprostorů. Budeme se zabývat otázkou, kdy jsou dva vektorové podprostory na sebe kolmé a jak to poznáme.

Více

Paměť počítače. alg2 1

Paměť počítače. alg2 1 Paměť počítače Výpočetní proces je posloupnost akcí nad daty uloženými v paměti počítače Data jsou v paměti reprezentována posloupnostmi bitů (bit = 0 nebo 1) Připomeňme: paměť je tvořena řadou 8-mi bitových

Více

PODPROGRAMY PROCEDURY A FUNKCE

PODPROGRAMY PROCEDURY A FUNKCE PODPROGRAMY PROCEDURY A FUNKCE Programy bez podprogramů Příklady: a) Napište program, který na obrazovku nakreslí čáru složenou ze znaků pomlčka. program Cara; b) Napište program, který na obrazovku nakreslí

Více

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; } Pole Kdybychom v jazyce C++chtěli načíst větší počet čísel nebo znaků a všechny bylo by nutné všechny tyto hodnoty nadále uchovávat v paměti počítače, tak by bylo potřeba v paměti počítače alokovat stejný

Více

2 Strukturované datové typy 2 2.1 Pole... 2 2.2 Záznam... 3 2.3 Množina... 4

2 Strukturované datové typy 2 2.1 Pole... 2 2.2 Záznam... 3 2.3 Množina... 4 Obsah Obsah 1 Jednoduché datové typy 1 2 Strukturované datové typy 2 2.1 Pole.................................. 2 2.2 Záznam................................ 3 2.3 Množina................................

Více

Programování v jazyku LOGO - úvod

Programování v jazyku LOGO - úvod Programování v jazyku LOGO - úvod Programovací jazyk LOGO je určen pro výuku algoritmizace především pro děti školou povinné. Programovací jazyk pracuje v grafickém prostředí, přičemž jednou z jeho podstatných

Více

Kombinatorika. Michael Krbek. 1. Základní pojmy. Kombinatorika pracuje se spočitatelnými (tedy obvykle

Kombinatorika. Michael Krbek. 1. Základní pojmy. Kombinatorika pracuje se spočitatelnými (tedy obvykle Kombinatorika Michael Krbek. Základní pojmy. Kombinatorika pracuje se spočitatelnými (tedy obvykle konečnými) strukturami a patří kvůli tomu mezi nejstarší oblasti matematiky. Je těžké podat přesný výčet

Více

Programujeme v softwaru Statistica

Programujeme v softwaru Statistica Programujeme v softwaru Statistica díl druhý Newsletter Statistica ACADEMY Téma: Programování, makra, skripty Typ článku: Návody V tomto článku si ukážeme další možnosti při psaní maker v softwaru Statistica.

Více

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT Číslo a název šablony Číslo didaktického materiálu Druh didaktického materiálu Autor Jazyk Téma sady didaktických materiálů Téma didaktického materiálu Vyučovací předmět Cílová skupina (ročník) Úroveň

Více

Úvod do informatiky. Miroslav Kolařík

Úvod do informatiky. Miroslav Kolařík Úvod do informatiky přednáška desátá Miroslav Kolařík Zpracováno dle R. Bělohlávek, V. Vychodil: Diskrétní matematika 2, http://phoenix.inf.upol.cz/esf/ucebni/dm2.pdf P. Martinek: Základy teoretické informatiky,

Více

NPRG030 Programování I, 2018/19 1 / :25:37

NPRG030 Programování I, 2018/19 1 / :25:37 NPRG030 Programování I, 2018/19 1 / 26 24. 9. 2018 10:25:37 Čísla v algoritmech a programech 10 26 Poloměr vesmíru 2651 studujících studentů MFF UK 3.142857... Ludolfovo číslo 10 16 stáří vesmíru v sekundách!!!

Více

Informatika 8. třída/6

Informatika 8. třída/6 Rekurze Jedním z důležitých principů pro návrh procedur je tzv. rekurze. Nejlépe uvidíme tento princip na příkladech dvou velmi jednoduchých procedur (hvězdička označuje násobení). Rekurze vlastně označuje

Více

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5 Obsah Obsah 1 Řídicí struktury 1 2 Podmínka 1 2.1 Podmínka typu case......................... 2 3 Příkaz skoku 3 4 Cykly 4 4.1 Cyklus s podmínkou na začátku................... 4 4.2 Cyklus s podmínkou

Více

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12. Vyhledávání doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava Prezentace ke dni 12. září 2016 Jiří Dvorský (VŠB TUO) Vyhledávání 201 / 344 Osnova přednášky

Více

2 Datové typy v jazyce C

2 Datové typy v jazyce C 1 Procedurální programování a strukturované programování Charakteristické pro procedurální programování je organizace programu, který řeší daný problém, do bloků (procedur, funkcí, subrutin). Původně jednolitý,

Více

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech 7 Formátovaný výstup, třídy, objekty, pole, chyby v programech Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost formátovanému výstupu,

Více

Algoritmizace řazení Bubble Sort

Algoritmizace řazení Bubble Sort Algoritmizace řazení Bubble Sort Cílem této kapitoly je seznámit studenta s třídícím algoritmem Bubble Sort, popíšeme zde tuto metodu a porovnáme s jinými algoritmy. Klíčové pojmy: Třídění, Bubble Sort,

Více

Sada 1 - Základy programování

Sada 1 - Základy programování S třední škola stavební Jihlava Sada 1 - Základy programování 17. Řadící algoritmy Digitální učební materiál projektu: SŠS Jihlava šablony registrační číslo projektu:cz.1.09/1.5.00/34.0284 Šablona: III/2

Více

- speciální symboly + - * / =., < > <> <= >= a další. Klíčová slova jsou chráněnými útvary, které nelze použít ve významu identifikátorů.

- speciální symboly + - * / =., < > <> <= >= a další. Klíčová slova jsou chráněnými útvary, které nelze použít ve významu identifikátorů. Základní symboly - písmena A B C Y Z a b c y z - číslice 0 1 2 9 - speciální symboly + - * / =., < > = a další - klíčová slova and array begin case const a další Klíčová slova jsou chráněnými útvary,

Více

5 Přehled operátorů, příkazy, přetypování

5 Přehled operátorů, příkazy, přetypování 5 Přehled operátorů, příkazy, přetypování Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně budou uvedeny detaily týkající se operátorů. Doba nutná k nastudování

Více

South Bohemia Mathematical Letters Volume 23, (2015), No. 1, DĚLENÍ KRUHU NA OBLASTI ÚVOD

South Bohemia Mathematical Letters Volume 23, (2015), No. 1, DĚLENÍ KRUHU NA OBLASTI ÚVOD South Bohemia Mathematical Letters Volume 23, (2015), No. 1, 113-122. DĚLENÍ KRUHU NA OBLASTI MAREK VEJSADA ABSTRAKT. V textu se zabývám řešením následujícího problému: Zvolíme na kružnici určitý počet

Více

Úvod do programování 10. hodina

Úvod do programování 10. hodina Úvod do programování 10. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015 Umíme z minulé hodiny Syntax Dvojrozměrné pole

Více

63. ročník Matematické olympiády 2013/2014

63. ročník Matematické olympiády 2013/2014 63. ročník Matematické olympiády 2013/2014 Úlohy ústředního kola kategorie P 2. soutěžní den Na řešení úloh máte 4,5 hodiny čistého času. Při soutěži je zakázáno používat jakékoliv pomůcky kromě psacích

Více

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT Název školy Gymnázium, Šternberk, Horní nám. 5 Číslo projektu CZ.1.07/1.5.00/34.0218 Šablona III/2 Inovace a zkvalitnění výuky prostřednictvím ICT Označení materiálu VY_32_INOVACE_Hor004 Vypracoval(a),

Více

Funkce, elementární funkce.

Funkce, elementární funkce. Kapitola 2 Funkce, elementární funkce. V této kapitole si se budeme věnovat studiu základních vlastností funkcí jako je definiční obor, obor hodnot. Připomeneme si pojmy sudá, lichá, rostoucí, klesající.

Více

DUM 06 téma: Tvorba makra pomocí VBA

DUM 06 téma: Tvorba makra pomocí VBA DUM 06 téma: Tvorba makra pomocí VBA ze sady: 03 tematický okruh sady: Tvorba skript a maker ze šablony: 10 Algoritmizace a programování určeno pro: 4. ročník vzdělávací obor: 18-20-M/01 Informační technologie

Více

Řešení úloh z TSP MU SADY S 1

Řešení úloh z TSP MU SADY S 1 Řešení úloh z TSP MU SADY S 1 projekt RESENI-TSP.CZ úlohy jsou vybírány z dříve použitých TSP MU autoři řešení jsou zkušení lektoři vzdělávací agentury Kurzy-Fido.cz Masarykova univerzita nabízí uchazečům

Více

Algoritmus pro hledání nejkratší cesty orientovaným grafem

Algoritmus pro hledání nejkratší cesty orientovaným grafem 1.1 Úvod Algoritmus pro hledání nejkratší cesty orientovaným grafem Naprogramoval jsem v Matlabu funkci, která dokáže určit nejkratší cestu v orientovaném grafu mezi libovolnými dvěma vrcholy. Nastudoval

Více

Už známe datové typy pro representaci celých čísel i typy pro representaci

Už známe datové typy pro representaci celých čísel i typy pro representaci Dlouhá čísla Tomáš Holan, dlouha.txt, Verse: 19. února 2006. Už známe datové typy pro representaci celých čísel i typy pro representaci desetinných čísel. Co ale dělat, když nám žádný z dostupných datových

Více

Pointery II. Jan Hnilica Počítačové modelování 17

Pointery II. Jan Hnilica Počítačové modelování 17 Pointery II 1 Pointery a pole Dosavadní způsob práce s poli zahrnoval: definici pole jakožto kolekce proměnných (prvků) jednoho typu, umístěných v paměti za sebou int pole[10]; práci s jednotlivými prvky

Více

VY_32_INOVACE_08_2_04_PR

VY_32_INOVACE_08_2_04_PR Ing. Petr Stránský VY_32_INOVACE_08_2_04_PR Příkazy vstupu - definice Výstupním zařízením může být obrazovka, tiskárna nebo soubor. Jednotlivé údaje se zapisují pomocí příkazu WRITE nebo WRITELN. Příkaz

Více

Poslední nenulová číslice faktoriálu

Poslední nenulová číslice faktoriálu Poslední nenulová číslice faktoriálu Kateřina Bambušková BAM015, I206 Abstrakt V tomto článku je popsán a vyřešen problém s určením poslední nenulové číslice faktoriálu přirozeného čísla N. Celý princip

Více

Aplikovaná informatika. Podklady předmětu Aplikovaná informatika pro akademický rok 2006/2007 Radim Farana. Obsah. Obsah předmětu

Aplikovaná informatika. Podklady předmětu Aplikovaná informatika pro akademický rok 2006/2007 Radim Farana. Obsah. Obsah předmětu 1 Podklady předmětu pro akademický rok 2006/2007 Radim Farana Obsah 2 Obsah předmětu, Požadavky kreditového systému, Datové typy jednoduché, složené, Programové struktury, Předávání dat. Obsah předmětu

Více

Struktura programu v době běhu

Struktura programu v době běhu Struktura programu v době běhu Miroslav Beneš Dušan Kolář Struktura programu v době běhu Vztah mezi zdrojovým programem a činností přeloženého programu reprezentace dat správa paměti aktivace podprogramů

Více

Digitální učební materiál

Digitální učební materiál Digitální učební materiál Číslo projektu: CZ.1.07/1.5.00/34.0548 Název školy: Gymnázium, Trutnov, Jiráskovo náměstí 325 Název materiálu: VY_32_INOVACE_145_IVT Autor: Ing. Pavel Bezděk Tematický okruh:

Více

Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí)

Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí) Programovací jazyky Programovací jazyky nižší assembler (jazyk symbolických instrukcí) vyšší imperativní (procedurální) Pascal, C/C++, Java, Basic, Python, php neimperativní (neprocedurální) Lisp, Prolog

Více

Předmět: Algoritmizace praktické aplikace

Předmět: Algoritmizace praktické aplikace Předmět: Algoritmizace praktické aplikace Vytvořil: Roman Vostrý Zadání: Vytvoření funkcí na stromech (reprezentace stromu haldou). Zadané funkce: 1. Počet vrcholů 2. Počet listů 3. Součet 4. Hloubka 5.

Více

NMIN101 Programování 1 2/2 Z --- NMIN102 Programování /2 Z, Zk

NMIN101 Programování 1 2/2 Z --- NMIN102 Programování /2 Z, Zk NMIN101 Programování 1 2/2 Z --- NMIN102 Programování 2 --- 2/2 Z, Zk Pavel Töpfer Katedra software a výuky informatiky MFF UK MFF Malostranské nám., 4. patro, pracovna 404 pavel.topfer@mff.cuni.cz http://ksvi.mff.cuni.cz/~topfer

Více

VÝUKOVÝ MATERIÁL. Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632 Číslo projektu

VÝUKOVÝ MATERIÁL. Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632 Číslo projektu VÝUKOVÝ MATERIÁL Identifikační údaje školy Vyšší odborná škola a Střední škola, Varnsdorf, příspěvková organizace Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632

Více

DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3

DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3 DobSort Úvod do programování Michal Krátký 1,Jiří Dvorský 1 1 Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programování, 2004/2005 V roce 1980 navrhl Dobosiewicz variantu (tzv. DobSort),

Více

Lokální definice (1) plocha-kruhu

Lokální definice (1) plocha-kruhu Lokální definice (1) syntaxe: (local (seznam definic) výraz) definice jsou dostupné pouze uvnitř příkazu local příklad: (local ( (define Pi 3.1415926) (define (plocha-kruhu r) (* Pi r r)) ) (plocha-kruhu

Více

Algoritmizace. 1. Úvod. Algoritmus

Algoritmizace. 1. Úvod. Algoritmus 1. Úvod Algoritmizace V dnešní době již počítače pronikly snad do všech oblastí lidské činnosti, využívají se k řešení nejrůznějších úkolů. Postup, který je v počítači prováděn nějakým programem se nazývá

Více

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu } 5. Operátor čárka, - slouží k jistému určení pořadí vykonání dvou příkazů - oddělím-li čárkou dva příkazy, je jisté, že ten první bude vykonán dříve než příkaz druhý. Např.: i = 5; j = 8; - po překladu

Více

MATURITNÍ TÉMATA Z MATEMATIKY

MATURITNÍ TÉMATA Z MATEMATIKY MATURITNÍ TÉMATA Z MATEMATIKY 1. Základní poznatky z logiky a teorie množin Pojem konstanty a proměnné. Obor proměnné. Pojem výroku a jeho pravdivostní hodnota. Operace s výroky, složené výroky, logické

Více

Sada 1 - Základy programování

Sada 1 - Základy programování S třední škola stavební Jihlava Sada 1 - Základy programování 04. Datové typy, operace, logické operátory Digitální učební materiál projektu: SŠS Jihlava šablony registrační číslo projektu:cz.1.09/1.5.00/34.0284

Více

Algoritmus pro generování normálních magických čtverců

Algoritmus pro generování normálních magických čtverců 1.1 Úvod Algoritmus pro generování normálních magických čtverců Naprogramoval jsem v Matlabu funkci, která dokáže vypočítat magický čtverec libovolného přípustného rozměru. Za pomocí tří algoritmů, které

Více

Základní způsoby: -Statické (přidělění paměti v čase překladu) -Dynamické (přiděleno v run time) v zásobníku na haldě

Základní způsoby: -Statické (přidělění paměti v čase překladu) -Dynamické (přiděleno v run time) v zásobníku na haldě Metody přidělování paměti Základní způsoby: -Statické (přidělění paměti v čase překladu) -Dynamické (přiděleno v run time) v zásobníku na haldě Důležitá hlediska jazykových konstrukcí: Dynamické typy Dynamické

Více

Syntaktická analýza. Implementace LL(1) překladů. Šárka Vavrečková. Ústav informatiky, FPF SU Opava

Syntaktická analýza. Implementace LL(1) překladů. Šárka Vavrečková. Ústav informatiky, FPF SU Opava Implementace LL(1) překladů Ústav informatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Poslední aktualizace: 6. ledna 2012 Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku

Více

PSK3-9. Základy skriptování. Hlavička

PSK3-9. Základy skriptování. Hlavička PSK3-9 Název školy: Autor: Anotace: Vyšší odborná škola a Střední průmyslová škola, Božetěchova 3 Ing. Marek Nožka Základy skriptování v unixovém shellu Vzdělávací oblast: Informační a komunikační technologie

Více

8 Třídy, objekty, metody, předávání argumentů metod

8 Třídy, objekty, metody, předávání argumentů metod 8 Třídy, objekty, metody, předávání argumentů metod Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost třídám a objektům, instančním

Více

Počítačové zobrazování fraktálních množin. J. Bednář*, J. Fábera**, B. Fürstová*** *Gymnázium Děčín **SPŠ Hronov ***Gymnázium Plasy

Počítačové zobrazování fraktálních množin. J. Bednář*, J. Fábera**, B. Fürstová*** *Gymnázium Děčín **SPŠ Hronov ***Gymnázium Plasy Počítačové zobrazování fraktálních množin J. Bednář*, J. Fábera**, B. Fürstová*** *Gymnázium Děčín **SPŠ Hronov ***Gymnázium Plasy *jurij.jurjevic@centrum.cz **icarosai@seznam.cz ***barborafurstova7@seznam.cz

Více

NP-úplnost problému SAT

NP-úplnost problému SAT Problém SAT je definován následovně: SAT(splnitelnost booleovských formulí) Vstup: Booleovská formule ϕ. Otázka: Je ϕ splnitelná? Příklad: Formule ϕ 1 =x 1 ( x 2 x 3 )jesplnitelná: např.přiohodnocení ν,kde[x

Více