Funkce a procedury. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 5 A0B36PR1 Programování 1

Podobné dokumenty
Část 1 Funkce, lokální proměnné a přidělování paměti. Funkce a procedury. Část 2 Cykly a řízení jejich průchodu. Část 3 Příklady

Základy algoritmizace 4. Problémy, algoritmy, data

Rozklad problému na podproblémy

5. přednáška - Rozklad problému na podproblémy

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

Řídicí struktury. alg3 1

Funkce, intuitivní chápání složitosti

Úvod do programování - Java. Cvičení č.4

Správa paměti. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta, 2016

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

6. Příkazy a řídící struktury v Javě

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Rozklad problému na podproblémy, rekurze

Algoritmizace a programování

Rozklad problému na podproblémy, rekurze

6 Příkazy řízení toku

Obsah přednášky. Příkaz for neúplný. Příkaz for příklady. Cyklus for each (enhanced for loop) Příkaz for příklady

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

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Algoritmizace a programování

Algoritmizace a programování. Ak. rok 2012/2013 vbp 1. ze 44

Abstraktní datové typy: zásobník

KTE / ZPE Informační technologie

Struktura programu v době běhu

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Řídící struktury, if, while, switch

Obsah. Úvod 11 Základy programování 11 Objektový přístup 11 Procvičování 11 Zvláštní odstavce 12 Zpětná vazba od čtenářů 12 Errata 13

Cykly. Základy programování 1 Martin Kauer (Tomáš Kühr)

Úvod do programování v jazyce Java

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

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

Z. Kotala, P. Toman: Java ( Obsah )

Algoritmizace a programování

Reprezentace základních typů, pole, funkce a procedury

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

Příkazy a řídicí struktury v Javě. Tomáš Pitner, upravil Marek Šabo

Algoritmizace a programování

Algoritmizace a programování

Reprezentace základních typů, pole, funkce a procedury

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Datové struktury. alg12 1

Programování v C++ 1, 1. cvičení

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

Řetězce a řídicí struktury

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

Část 1 Reprezentace základních typů. Reprezentace základních typů, pole, funkce a procedury. Část 3 Funkce a procedury.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Obsah přednášky. programovacího jazyka. Motivace. Princip denotační sémantiky Sémantické funkce Výrazy Příkazy Vstup a výstup Kontinuace Program

Rekurzivní algoritmy

11. Přehled prog. jazyků

8. Rekurze. doc. Ing. Jiří Vokřínek, Ph.D. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze

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

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

1. Programování proti rozhraní

Řídicí struktury, výrazy a funkce

Řídicí příkazy KAPITOLA 3. Vstup znaků z klávesnice

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

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

Programování v C++ 2, 4. cvičení

Algoritmizace. Cíle předmětu

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

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

IUJCE 07/08 Přednáška č. 6

Úvod do programovacích jazyků (Java)

Příkazy if, while, do-while, for, switch

Funkce pokročilé možnosti. Úvod do programování 2 Tomáš Kühr

Úvod do programovacích jazyků (Java)

Řídící struktury, if, while, switch

Řetězce a řídicí struktury

1. Téma 12 - Textové soubory a výjimky

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

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ě

Algoritmizace. Algoritmizace (Y36ALG), Šumperk - 1. přednáška 1

DSL manuál. Ing. Jan Hranáč. 27. října V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v

3. Řízení běhu programu

Přednáška 7. Celočíselná aritmetika. Návratový kód. Příkazy pro větvení výpočtu. Cykly. Předčasné ukončení cyklu.

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

Více o konstruktorech a destruktorech

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Správa paměti. doc. Ing. Miroslav Beneš, Ph.D. katedra informatiky FEI VŠB-TUO A-1007 /

Příkaz while. while (podmínka) { příkaz; } Příklad: int i=0; while (i < 10) { System.out.println(i); i++; } // vypíše čísla od 0 do 9

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

Větvení a cykly. Úvod do programování 1 Tomáš Kühr

Část 1 Soubory a vytvoření projektu. Řetězce a řídicí struktury. Část 2 Připomínka (NSD) Část 3 Textové řetězce, operátory a načítání vstupu

Výčtový typ strana 67

Úvod do programování v jazyce Java

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ě

Objektově orientované programování

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Lineární datové struktury

Dekompozice problému, rekurze

Ukazatele, paměťové třídy, volání funkcí

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

Základní datové struktury

Základní stavební prvky algoritmu

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Transkript:

Funkce a procedury Jan Faigl Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Přednáška 5 A0B36PR1 Programování 1 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 1 / 54

Část 1 Funkce, lokální proměnné a přidělování paměti Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 2 / 54

Část 2 Cykly a řízení jejich průchodu Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 3 / 54

Část 3 Příklady Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 4 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Část I Funkce, lokální proměnné a přidělování paměti Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 5 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Přetížení jména funkce Funkce lišící se v počtu nebo typu parametrů se mohou jmenovat stejně Přetěžování jmen (overloadings of names) int max(int x, int y) { return x > y? x : y; int max(int x, int y, int z) { return max(x, max(y, z)); double max(double x, double y) { return x > y? x : y; void execute() { System.out.println(max(3, 5)); System.out.println(max(4, 7, 5)); System.out.println(max(1.4, 4.3)); lec05/demofunctionnameoverloading.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 7 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Předání návratové hodnoty funkce return 1/2 Předání hodnoty volání funkce je předepsáno voláním return int dosomethinguseful() { int ret = -1;... return ret; Jak často umisťovat volání return ve funkci? int dosomething() { if (!cond1 && cond2 && cond3 ) {... do some long code... return 0; int dosomething() { if (cond1) { return 0; if (!cond2) { return 0; if (!cond3) { return 0;... some long code... return 0; http://llvm.org/docs/codingstandards.html Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 9 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Předání návratové hodnoty funkce return 2/2 Volání return na začátku funkce může být přehlednější Podle hodnoty podmínky je volání funkce ukončeno Kódovací konvence může také předepisovat použití nejvýše jednoho volání return Má výhodu v jednoznačné identifikací místa volání, můžeme pak například jednoduše přidat další zpracování výstupní hodnoty funkce. Dále není doporučováno bezprostředně používat else za voláním return (nebo jiným přerušení toku programu), např. case 10: if (...) {... return 1; else { if (cond) {... return -1; else { break; case 10: if (...) {... return 1; else { if (cond) {... return -1; break; Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 10 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Rozsah platnosti lokální proměnné Lokální proměnné mají rozsah platnosti pouze uvnitř bloku nebo funkce int a = 10; //lokalni promenna if (a == 10) { int a = 1; // v Jave nelze zastinit lokalni // promennou jinou lokalni // promennou riziko chyby // int b = 20; // lokalni promena s platnosti // uvnitr bloku a = b + 10; // b = 10; // b neni platnou promennou Globální proměnné, které mají rozsah platnosti kdekoliv v programu můžeme v Javě realizovat jako třídní proměnné, případně jako atributy objektu. K tomu však potřebujeme znát základy objektově orientovaného programování, viz přednáška 7, 8 a 9. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 12 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Přidělování paměti proměnným Přidělením paměti proměnné rozumíme určení pamětového místa pro uložení hodnoty proměnné (příslušného typu) v paměti počítače Lokálním proměnným a parametrům funkce se paměť přiděluje při volání funkce. Paměť zůstane přidělena jen do návratu z funkce. Při návratu funkce se přidělené paměťové místo uvolní pro další použití Paměť se alokuje z rezervovaného místa zásobník (stack) Dynamické přidělování paměti Alokace paměti řetězce nebo pole se provádí příkazem new Alokace objektů Paměť se alokuje z rezervovaného místa halda (heap) Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 14 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Alokace paměti Java program běží ve virtuálním stroji JVM (Java Virtual Machine) Při spuštění JVM specifikujeme kolik fyzické paměti dedikujeme virtuálnímu stroji Podobně funguje fyzický limit na úrovni OS Paměť je rozdělena na zásobník (stack) a haldu (heap) Při běhu programu paměť přiděluje správce paměti (součást JVM) Dynamicky přidělovanou paměť (voláním new) v Javě spravuje a automaticky uvolňuje Garbage Collector Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 15 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Zásobník Úseky paměti přidělované lokálním proměnným a parametrům funkce tvoří tzv. zásobník (stack) Úseky se přidávají a odebírají Vždy se odebere naposledy přidaný úsek LIFO last in, first out Na zásobník se ukládá volání funkce Na zásobník se také ukládá návratová hodnota funkce a také hodnota program counter původně prováděné instrukce, před voláním funkce Ze zásobníku se alokují proměnné parametrů funkce Argumenty (parametry) jsou de facto lokální proměnné Opakovaným rekurzivním voláním funkce můžeme velice rychle zaplnit velikost přiděleného zásobníku Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 16 / 54

Jména funkcí Předání návratové hodnoty funkce Rozsah platnosti proměnných Paměť lokálních proměnných Příklad rekurzivního volání funkce void printvalue(int v) { System.out.println("value: " + v); printvalue(v + 1); demo.printvalue(1); lec05/demostackoverflow.java Vyzkoušejte si program pro různé hodnoty přidělené paměti pro zásobník java DemoStackOverflow 2>err tail -n 2 value: 9918 value: 9919 java -Xss10m DemoStackOverflow 2>err tail -n 2 value: 137803 value: 137804 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 17 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Část II Cykly a řízení jejich průchodu Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 18 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Cykly Cyklus for a while testuje podmínku opakování před vstupem do těla cyklu for inicializace, podmínka a změna řídicí proměnné součást syntaxe for (int i = 0; i < 5; i++) {... while řídicí proměnná v režii programátora int i = 0; while (i < 5) {... i += 1; Cyklus do testuje podmínku opakování cyklu po prvním provedení cyklu int i = -1; do {... i += 1; while (i < 5); Ekvivalentní provedení 5ti cyklů. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 20 / 54 ano ano ne ne

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Předčasné ukončení průchodu cyklu příkaz continue Někdy může být užitečné ukončit cyklus v nějakém místě uvnitř těla cyklu Například ve vnořených if příkazech Příkaz continue předepisuje ukončení průchodu těla cyklu Platnost pouze v těle cyklu! for (int i = 0; i < 10; ++i) { System.out.print("i:" + i + " "); if (i % 3!= 0) { continue; System.out.println(" "); javac DemoContinue.java java DemoContinue i:0 i:1 i:2 i:3 i:4 i:5 i:6 i:7 i:8 i:9 lec05/democontinue.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 22 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Předčasné ukončení vykonávání cyklu příkaz break Příkaz break předepisuje ukončení cyklu Program pokračuje následujícím příkazem po cyklu for (int i = 0; i < 10; ++i) { System.out.print("i:" + i + " "); if (i % 3!= 0) { continue; System.out.println(" "); if (i > 5) { break; javac DemoBreak.java java DemoBreak i:0 i:1 i:2 i:3 i:4 i:5 i:6 lec05/demobreak.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 23 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Příklad ukončení cyklu lineárního vyhledávání String[] months = { "jan", "feb", "mar", "apr", "may", " jun", "jul", "aug", "sep", "oct", "nov", "dec"; String monthstr = (args.length > 0)? args[0] : "Jun"; int month = -1; monthstr = monthstr.substring(0, 3); for(int i = 0; i < months.length; ++i) { if (monthstr.equalsignorecase(months[i])) { month = i + 1; break; if (month >= 0 && month < months.length) { System.out.println("Parsed month " + monthstr + " is " + month + " month of the year"); else { System.err.println("Month has not been matched"); lec04/demoarraymonth.java lec05/demoarraymonth.java Při nalezení odpovídajícího řetězce je zbytečné testovat další prvky pole. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 24 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Konečnost cyklů 1/3 Konečnost algoritmu pro přípustná data v konečné době skončí 2. přednáška Aby byl algoritmus konečný musí každý cyklus v něm uvedený skončit po konečném počtu kroků Jedním z důvodu neukončení programu je zacyklení Program opakovaně vykoná cyklus, jehož podmínka ukončení není nikdy splněna. while (i!= 0) { j = i - 1; Cyklus se provede jednou, nebo neskončí. Záleží na hodnotě i před voláním cyklu Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 26 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Konečnost cyklů 2/3 Základní pravidlo pro konečnost cyklu Provedením těla cyklu se musí změnit hodnota proměnné použité v podmínce ukončení cyklu for (int i = 0; i < 5; i++) {... Uvedené pravidlo konečnost cyklu nezaručuje int i = -1; while( i < 0 ) { i = i - 1; Konečnost cyklu závisí na hodnotě proměnné před vstupem do cyklu. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 27 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Konečnost cyklů 3/3 while (i!= n) {... //prikazy nemenici hodnotu promenne i i++; lec05/demoloopbyte.java Vstupní podmínka konečnosti uvedeného cyklu i n pro celá čísla Jak by vypadala podmínka pro proměnné typu double? lec05/demoloop.java Splnění vstupní podmínky konečnosti cyklu musí zajistit příkazy předcházející příkazu cyklu Zabezpečený program testuje přípustnost vstupních dat Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 28 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Příklad test, je-li zadané číslo prvočíslem public boolean isprimenumber(int n) { boolean ret = true; for (int i = 2; i <= (int)math.sqrt(n); ++i) { if (n % i == 0) { ret = false; break; return ret; lec05/demoprimenumber.java Po nalezení prvního dělitele je zbytečné pokračovat ve zkoušení dalších hodnot Hodnota výrazu (int)math.sqrt(n) se v cyklu nemění a je zbytečné výraz opakovaně vyhodnocovat boolean ret = true; final int maxbound = (int)math.sqrt(n); for (int i = 2; i <= maxbound ; ++i) {... V JVM bude výraz pravděpodobně vyhodnocen pouze jednou v důsledku optimalizace kódu za běhu Java HotSpot Virtual Machine Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 30 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Vnořené cykly break ukončuje vnitřní cyklus for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.println("i-j: " + i + "-" + j); if (j == 1) { break; Vnější cyklus můžeme ukončit příkazem break se jménem outer: for (int i = 0; i < 5; i++) { for (int j = 0; j < 3; j++) { System.out.println("i-j: " + i + "-" + j); if (j == 2) { break outer; i-j: 0-0 i-j: 0-1 i-j: 1-0 i-j: 1-1 i-j: 2-0 i-j: 2-1 i-j: 0-0 i-j: 0-1 i-j: 0-2 lec05/demolabeledbreak.java http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 32 / 54

Cykly Řízení průchodu cyklu Konečnost cyklu Příklad ukončení cyklu Vnořené cykly Kódovací konvence Příkazy break a continue v podstatě odpovídají příkazům skoku. Obecně můžeme říci, že příkazy break a continue nepřidávají příliš na přehlednosti Nemyslíme tím break v příkazu switch Přerušení cyklu break nebo continue můžeme využít v těle dlouhých funkcí a vnořených cyklech Ale funkce bychom měli psát krátké a přehledné Je-li funkce (tělo cyklu) krátké je význam break/continue čitelný Podobně použití na začátku bloku cyklu např. jako součást testování splnění předpokladů, je zpravidla přehledné Použití uprostřed bloku je však už méně přehledné a může snížit čitelnost a porozumění kódu https://www.scribd.com/doc/38873257/ Knuth-1974-Structured-Programming-With-Go-to-Statements Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 33 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Část III Příklady Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 34 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Příklad Výpočet největšího společného dělitele 1/3 Vstup - celá čísla x a y Výstup - největší společný dělitel x a y, tj. celé číslo d takové, že x%d == 0 a y%d == 0 a zároveň d je maximální možné. Základní varianta int getgreatestcommondivisor(int x, int y) { int d = x < y? x : y; while ( (x % d!= 0) (y % d!= 0) ) { d = d - 1; return d; lec03/demogcd.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 36 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Příklad Výpočet největšího společného dělitele 2/3 Místo výběru menšího z čísel x a y vnoříme do těla hlavního cyklu dva cykly zmenšující hodnoty aktuální hodnoty x a y int getgreatestcommondivisorloops(int x, int y) { while (x!= y) { while (x > y) { x = x - y; while (y > x) { y = y - x; return x; lec05/demogcd.java Vnitřní cykly počítají nenulový zbytek po dělení většího čísla menším Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 37 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Příklad Výpočet největšího společného dělitele 3/3 Vnitřní cykly můžeme nahradit přímým výpočtem zbytku po dělení operátorem % int getgreatestcommondivisoreuclid(int x, int y) { int remainder = x % y; while (remainder!= 0) { x = y; y = remainder; remainder = x % y; return y; lec05/demogcd.java Euklidův algoritmus Určíme zbytek po dělení daných čísel Zbytkem dělíme dělitele a určíme nový zbytek, až dosáhneme nulového zbytku Poslední nenulový zbytek je největší společný dělitel Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 38 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Rozklad problému na podproblémy Postupný návrh programu rozkladem problému na podproblémy Zadaný problém rozložíme na podproblémy Pro řešení podproblémů zavedeme abstraktní příkazy S abstraktními příkazy sestavíme hrubé řešení Abstraktní příkazy realizujeme jako procedury (funkce) Rozklad problému na podproblémy ilustrujeme na příkladu hry NIM Pravděpodobně první počítačová hra (1951) Hra dvou hráčů v odebírání herních kamenů (nebo např. zápalek) Čínská hra ve sbírání kamenů Tsyanchidzi L Année Derniere a Marienbad http://www.jot101.com/2013/09/nim-first-computer-game-1951_19.html Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 40 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM - Pravidla Pravidla Hráč zadá počet herních kamenů (např. od 15 do 35) Pak se střídá se strojem v odebírání; odebrat lze 1, 2 nebo 3 kameny Prohraje ten, kdo odebere poslední herní kámen Dílčí problémy Zadání počtu kamenů Odebrání kamenů hráčem Odebrání kamenů strojem Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 41 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Příklad průběhu hry Zadej počet kamenů (15 až 35): 18 Stav hry Počet kamenů ve hře Kdo je na tahu počítač (P) nebo hráč (H) Průběh: 1. Počet kamenů 18; Kolik odeberete? 1 (H) 2. Počet kamenů 17; Odebírám 1 (P) 3. Počet kamenů 16; Kolik odeberete? 3 (H) 4. Počet kamenů 13; Odebírám 1 (P) 5. Počet kamenů 12; Kolik odeberete? 3 (H) 6. Počet kamenů 9; Odebírám 1 (P) 7. Počet kamenů 8; Kolik odeberete? 3 (H) 8. Počet kamenů 5; Odebírám 1 (P) 9. Počet kamenů 4; Kolik odeberete? 3 (H) 10. Počet kamenů 1; Odebírám 1 (P) Hráč vyhrál, počítač odebral poslední kámen. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 42 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace NIM pravidla pro odebírání Počet kamenů nevýhodných pro protihráče je 1, 5, 9,..., obecně 4n + 1, kde n je celé nezáporné číslo Stroj musí z počtu kamenů K odebrat x kamenů, aby platilo K x == 4n + 1 x == (K 1) 4n, tj. hledáme zbytek po dělení 4 x (K 1) mod 4 x (K 1)%4 Je-li x == 0, je okamžitý počet kamenů pro stroj nevýhodný a bude-li protihráč postupovat správně, stroj prohraje. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 43 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Hrubý návrh řešení int numberofstones; boolean machine = true; numberofstones = getnumberofstones(limits); do { if (machine) { machineturn(); else { humanturn(); machine =!machine; //change the player while (numberofstones > 0); return machine? "Machine win!" : "Human win!"; Podproblémy getnumberofstones, machineturn a humanturn reprezentují abstraktní příkazy, které implementujeme jako funkce vracející počet kamenů k odebrání. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 44 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Podrobnější návrh 1 final int MIN_INIT_STONES = 15; 2 final int MAX_INIT_STONES = 35; 3 boolean machine = true; 4 int numberofstones = getnumberofstones(limits); 5 6 if ( 7 numberofstones < MIN_INIT_STONES 8 numberofstones > MAX_INIT_STONES 9 ) { 10 return "Given number of stones is out of range"; 11 12 13 do { 14 if (machine) { 15 numberofstones -= machineturn(numberofstones); 16 else { 17 numberofstones -= humanturn(numberofstones); 18 19 machine =!machine; //change the player 20 while (numberofstones > 0); 21 22 return machine? "Machine win!" : "Human win!"; Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 45 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Implementace 1/4 Scanner scan; int getnumberofstones(int min, int max) { int n = -1; System.out.print("Enter number of stones in range [ " + min + ", " + max + " ]: "); n = scan.nextint(); return (n >= min && n <= max? n : -1); lec05/demonim.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 46 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Implementace 2/4 int humanturn(int n) { int r = 0; while(r!= 1 && r!= 2 && r!= 3) { System.out.print("No. of stones is " + n + ". How many stones you will take: " ); r = scan.nextint(); return r; lec05/demonim.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 47 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Implementace 3/4 int machineturn(int n) { int r = (n - 1) % 4; if (r == 0) { r = 1; System.out.println("No. of stones is " + n + ". I take " + r + "."); return r; lec05/demonim.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 48 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Implementace 4/5 1 public String play(boolean machinestart) { 2 final int MIN_INIT_STONES = 15; 3 final int MAX_INIT_STONES = 35; 4 5 boolean machine = machinestart; 6 7 int numberofstones = getnumberofstones(min_init_stones, MAX_INIT_STONES); 8 if (numberofstones < MIN_INIT_STONES numberofstones > MAX_INIT_STONES) { 9 return "Given number of stones is out of range"; 10 11 do { 12 if (machine) { 13 numberofstones -= machineturn(numberofstones); 14 else { 15 numberofstones -= humanturn(numberofstones); 16 17 machine =!machine; 18 while(numberofstones > 0); 19 return machine? "Machine win!" : "Human win!"; 20 lec05/demonim.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 49 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Hra NIM Implementace 5/5 public static void main(string[] args) { DemoNIM nim = new DemoNIM(); String result = nim.play(true); //machine start true/false System.out.println("Result of the game is: " + result); lec05/demonim.java Vyzkoušejte si program sami napsat a otestujte jej pro případ kdy začíná počítač nebo člověk! Kdo vyhrává při aplikování optimální strategie? Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 50 / 54

Výpočet největšího společného dělitele Rozklad problému na podproblémy Rekurze vs Iterace Výpočet faktoriálu Iterace n! = n(n 1)(n 2)... 2 1 int factoriali(int n) { int f = 1; for(; n > 1; --n) { f *= n; return f; Rekurze n! = 1 pro n 1 n! = n(n 1)! pro n > 1 int factorialr(int n) { int f = 1; if (n > 1) { f = n * factorialr(n-1); return f; lec05/demofactorial.java Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 52 / 54

Diskutovaná témata Shrnutí přednášky Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 53 / 54

Diskutovaná témata Diskutovaná témata Funkce, jejich jména a předání návratové hodnoty příkazem return Lokální proměnné a alokace paměti Cykly a řízení průchodu cyklu, příkazy break a continue Příklady dekompozice problému a jeho řešení Výpočet největšího společného dělitele Hra NIM Výpočet faktoriálu iteračně a rekurzí Příště: Rekurze a iterace Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 54 / 54