Čá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

Podobné dokumenty
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

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

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

Struktura programu v době běhu

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

Úvod do programování v jazyce Java

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)

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

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

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

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

Algoritmizace a programování

Algoritmizace a programování

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

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

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/

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

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

Algoritmizace a programování

Datové struktury. alg12 1

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

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

Řetězce a řídicí struktury

Čá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

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

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

11. Přehled prog. jazyků

Řídicí struktury, výrazy a funkce

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

1. Programování proti rozhraní

Rekurzivní algoritmy

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

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

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

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

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

Algoritmizace. Cíle předmětu

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

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.

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

Úvod do programovacích jazyků (Java)

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

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

Řetězce a řídicí struktury

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

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

Úvod do programovacích jazyků (Java)

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

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

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

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ě

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

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

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.

Více o konstruktorech a destruktorech

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

Ú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

Čá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

Úvod do programování v jazyce Java

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

Výčtový typ strana 67

Objektově orientované programování

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

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

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

Lineární datové struktury

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

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ě

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 )/ ;

Základní datové struktury

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

První kapitola úvod do problematiky

Dekompozice problému, rekurze

Transkript:

Část 1 Funkce, lokální proměnné a přidělování paměti 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 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 1 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 2 / 54 Část 2 Cykly a řízení jejich průchodu Část 3 Příklady Cykly Řízení průchodu cyklu Konečnost cyklu Výpočet největšího společného dělitele Rozklad problému na podproblémy Příklad ukončení cyklu Rekurze vs Iterace Vnořené cykly Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 3 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 4 / 54

Čá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 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 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 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 { case 10: if () { return 1; else { if (cond) { return -1; Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 10 / 54

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 Alokace paměti 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 Zásobník 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 Ú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 15 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 16 / 54

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 Část II Cykly a řízení jejich průchodu 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 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 18 / 54 Předčasné ukončení průchodu cyklu příkaz continue 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); ano ano ne ne 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 for (int i = 0; i < 10; ++i) { System.out.print("i:" + i + " "); if (i % 3!= 0) { continue; System.out.println(" "); Platnost pouze v těle cyklu! 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 Ekvivalentní provedení 5ti cyklů. Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 20 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 22 / 54

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

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 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) { 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 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; 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 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

Příklad Výpočet největšího společného dělitele 1/3 Část III Příklady 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 34 / 54 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 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 36 / 54 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

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 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 40 / 54 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 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 41 / 54 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

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 Hra NIM Implementace 1/4 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 Hra NIM Implementace 2/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 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 46 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 47 / 54

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 Hra NIM Implementace 5/5 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 faktoriálu 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? 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 50 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 52 / 54

Diskutovaná témata Diskutovaná témata Diskutovaná témata Shrnutí přednášky 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 53 / 54 Jan Faigl, 2015 A0B36PR1 Přednáška 5: Funkce a procedury 54 / 54