====== Den 4 ====== ===== Opakování z minulých dnů ===== === Úkol 1 === Naprogramujte výpočet hodnoty čísla Pi pomocí metody Monte Carlo (viz výklad na cvičení). * Na vstupu uživatel zadá, na kolik desetinných míst by chtěl Pi spočítat. * Po každých sto iteracích uložte současný mezivýsledek do seznamu. Seznam po doběhnutí výpočtu vytiskněte, abychom demonstrovali postupné zpřesňování výsledku. Pokud bude mít seznam více než sto prvků, vytiskněte pouze prvních sto. Pro kontrolu dosavadní přesnosti můžete váš výsledek porovnat s konstantou pi, která je již v Pythonu k dispozici. import math error = abs(moje_pi - math.pi) [[courses:pri-bootcamp:solutions#Den 4 - Úkol 1|Řešení]] ---- === Úkol 2 === Vytvořte program, který vypíše zadaný měsíc zadaného roku společně s jeho jménem. Je nanejvýše vhodné zvolit nějaký pevný bod (datum včetně dne v týdnu) od kterého se bude výpočet odvíjet. Přehlednosti kalendáře lze nejsnáze dosáhnout formátovaným výstupem: number = 9 print("%2d " % (number)) # lehce zastaraly # nebo print("{:2d} ".format(number)) # doporuceny zpusob # nebo print(f"{number:2d} ") # od Python 3.6 Při tvorbě programu nejprve zanebejte přestupné roky. Až vám bude program fungovat, přidejte **přestupné roky** -- každý rok, který je beze zbyku dělitelný čtyřmi, s výjimkou celých století, která nejsou beze zbytku dělitelná 400 __**Příklad:**__ **Vstup** Zadejte rok: 2017 Zadejte mesic: 9 **Výstup** ZARI 2017 PO UT ST CT PA SO NE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [[courses:pri-bootcamp:solutions#Den 4 - Úkol 2|Řešení]] ---- === Úkol 3 === Napište program, který provede skalární součin dvou vektorů. Na vstupu uživatel zadá rozměr obou vektorů. Program pak **náhodně vygeneruje** dva vektory specifikované délky a spočítá jejich skalární součin. Program oba vygenerované vektory i výsledek jejich skalárního součinu potom vytiskne. [[https://cs.wikipedia.org/wiki/Skal%C3%A1rn%C3%AD_sou%C4%8Din|Skalární součin (Wikipedia)]] je součet součinů jednotlivých prvků ve vektoru. **Příklad** [a1 a2 a3 ... an]. [b1 b2 b3 ... bn] = a1.b1 + a2.b2 + a3.b3 + ... an.bn Pro větší přehlednost vypistujte čísla naformátovaná na pevný počet desetinných míst (například 2). __**Příklad**__ **Vstup** Zadejte dimenzi (rozmer) vektoru: 2 **Výstup** [0.25 2].[3 7.5] = 15.75 __**Návrh na rozšíření**__ Program namísto vygenerování dvou náhodných vektorů umožní uživateli postupně načíst oba vektory a případně ošetří jejich různou délku. [[courses:pri-bootcamp:solutions#Den 4 - Úkol 3|Řešení]] ---- === Úkol 4 === Napište program, který sečte po prvcích dvě matice. Na vstupu zadá uživatel velikost obou matic. Program poté **náhodně vygeneruje** a [[https://cs.wikipedia.org/wiki/S%C4%8D%C3%ADt%C3%A1n%C3%AD_matic|sečte matice]]. Po ukončení výpočtu program vytiskne obě vygenerované matice a výslednou matici. __**Příklad**__ **Vstup** Zadejte dimenzi (rozmer) matic: 2 **Výstup** 3 1.5 2.1 1 + 0.5 2 1 1.3 = 3.5 3.5 3.1 2.3 následně upravte program tak aby provedl: - odčítání - násobení všech prvků matice číslem Poté spojte předchozí operace a vytvořte kalkulačku, které předáte velikost matice a operaci. Pro větší přehlednost vypistujte čísla naformátovaná na pevný počet desetinných míst. __**Příklad**__ **Vstup** Zadejte dimenzi matic: 2 Zadejte operaci (+/-/*): - **Výstup** 4 3.5 1.5 12.5 - 3 1.2 1 11 = 1 2.3 0.5 1.5 **Vstup** Zadejte dimenzi matic: 2 Zadejte operaci (+/-/*): * **Výstup** 4 * 0.5 1.2 11 10.5 = 2 4.8 44 42 __**Návrh na rozšíření**__ Upravte program tak, aby jednotlivé matice mohl uživatel přímo zadat. [[courses:pri-bootcamp:solutions#Den 4 - Úkol 4|Řešení]] ---- === Úkol 5 === Již známe funkci **sort()**, která seřadí prvky seznamu vzestupně podle velikosti. Napište nyní program/funkci, který pomocí algoritmu //Selection sort// (viz výklad na cvičení) daný seznam seřadí bez použití funkce **sort()**. Rychlejší z vás si mohou //Selection sort// nastudovat sami -- například [[https://cs.wikipedia.org/wiki/%C5%98azen%C3%AD_v%C3%BDb%C4%9Brem|zde]] [[courses:pri-bootcamp:solutions#Den 4 - Úkol 5|Řešení]] ---- ===== Funkce ===== Funkce je uzavřený, znovupoužitelný blok kódu, který umí splnit nějaký konkrétní úkol. Definovanou funkci pak můžeme kdekoliv v našem programu zavolat jedním příkazem. Po jejím zavolání se funkce celá provede a splní námi požadovaný úkol. Definice funkcí se zejména vyplatí v případech, kdy máme v našem programu nějaký dílčí úlok, který během programu potřebujeme vykonávat na více různých místech. Když řešení takového dílčího úkolu budeme mít definované jako samostatnou funkci, velmi nám to ušetří psaní a zpřehlední kód. ====Definice funkce:==== Každá funkce má **název**, kterým funkci budeme později volat. Dále musíme definovat, jestli do funkce budou vstupovat nějaké **vstupní paramtery** (vstupní proměnné), se kterými bude funkce pracovat. Vstupních proměnných může být libovolně mnoho a mohou být libovolných datových typů. Následuje samotný funkční kód. Pokud má funkce vracet nějakou návratovou hodnotu, použijeme pro její vrácení klíčové slovo **return.** V jazyce Python obecně vypadá definice funkce takto: def nazev_funkce(vstupni_parametry): kod, který ma byt vykonan * Za názvem funkce vždy musí být závorky. V případě, že funkce nepříjmá žádné vstupní parametry, necháme závorky prázdné. ====Příklady definic a volání funkcí==== Zde je příklad definice funkce //say_hello// bez vstupních parametrů a bez návratové hodnoty, která má vytisknout pozdrav. def say_hello(): print("Dobry den, vitejte u vykladu funkci.") A zde je příklad definice funkce //get_max//, která hledá větší ze dvou čísel. Vstupními parametry jsou dvě čísla k posouzení a návratovou hodnotou nalezené maximum. def get_max(a, b): if (a > b): return a else: return b Nadefinované funkce pak můžeme kdekoliv ve svém programu zavolat. Příklad programu, kde využijeme uvedené funkce může vypadat třeba takto: say_hello() number1 = 5 number2 = 3 print("Zkusime najit vetsi cislo z dvojice cisel " + str(number1) + " a " + str(number2) + ".") bigger_number = get_max(number1, number2) print("Vetsi je cislo " + str(bigger_number) + ".") Takový program bude mít následující výstup: Dobry den, vitejte u vykladu funkci. Zkusime najit vetsi cislo z dvojice cisel 5 a 3. Vetsi je cislo 5. ==== Úkoly ==== === Úkol 1 === Definujte dvě metody sloužící k výpočtu a posouzení hodnoty BMI (body mass index). * První metoda přijme dva parametry: hmotnost člověka a jeho výšku. Funkce vrátí hodnotu BMI takového člověka. BMI = hmotnost[kg] / výška[m] 2 * Druhá metoda přijme jako parametr hodnotu BMI. Pokud je BMI < 18, vypíše "Podvyziveny", pro BMI v intervalu <18, 30> vypíše "V poradku" a pro BMI > 30 vypíše "Trpi nadvahou". [[courses:pri-bootcamp:solutions#Den 4 - Funkce - Úkol 1|Řešení]] ---- === Úkol 2 === Vytvořte knihovnu funkcí jednoduché pokladny. V modulu //pokladna.py// definujte následující funkce: * Funkce **read_input()**, která od uživatele postupně načítá ceny jednotlivých položek (kladná čísla). Načítání uživatel ukončí zadáním čísla 0. Funkce pak vrátí načtené částky uložené v poli. * Funkce **get_sum(array)**, která jako vstupní parametr přijme pole s čísly (načtenými částkami) a vrátí jejich součet. * Funkce **get_max(array)**, která v poli najde nejvyšší částku. * Funkce **get_min(array)**, která v poli najde nejmenší částku. * Funkce **get_avg(array)**, která spočítá průměrnou cenu na jednu položku z částek uložených v poli. * Funkce **array_contains(array, number)** která vrátí //True// nebo //False// podle toho, jestli pole obsahuje nějakou konkrétní částku (číslo). * Funkce **do_payment()**, která načte částky k zaplacení a o útratě nám vypíše informace, které umíme pomocí výše zadaných funkcí zjistit. Nyní ve stejné složce, kde máte uložený soubor pokladna.py vytvořte jiný soubor, importujte si do něj svou knihovnu pokladních funkcí a vyzkoušejte, že je můžete volat i v jiném souboru, než kde jsou definovány. Import můžeme provést dvojím způsobem.\\ Jedna možnost je importovat celý modul se všemi funkcemi v něm definovanými. Když provedeme import tímto způsobem a budeme z něj chtít zavolat nějakou funkci, provedeme to obecně příkazem ve tvaru //nazev_modulu.nazev_funkce(parametry)//. V našem programu to může vypadat takto: import pokladna bill = pokladna.read_input() ... Druhá možnost je importovat pouze nějakou konkrétní funkci, ne celý modul. V tomto případě při volání funkce neuvádíme název modulu, v němž je funkce definována. Tento postup by vypadal následovně: from pokladna import read_input bill = read_input() ... Při tvorbě větších programů je běžné vytvářet si pro určité typy úkonů knihovny funkcí a pak si tyto funkce jinde v projektu pouze volat. Díky tomuto konceptu se mohou projekty dělit do menších souborů a udržovat přehledné. Zároveň nám většina programovacích jazyků nabízí velké množství vlastních knihoven s funkcemi, jejichž využíváním si mnohdy můžeme výrazně ušetřit práci (v Pythonu jsme se zatím setkali s knihovnou //math// a //random//). [[courses:pri-bootcamp:solutions#Den 4 - Funkce - Úkol 2|Řešení]] ---- === Úkol 3 === Vytvořte funkci, které je předán jako parametr seznam čísel a dva číselné indexy. Funkce v seznamu prohodí čísla na zadaných pozicích. cisla = [5, 7, 6, 8] prohod(cisla, 1, 2) print(cisla) # vypise [5, 6, 7, 8] [[courses:pri-bootcamp:solutions#Den 4 - Funkce - Úkol 3|Řešení]] ---- === Úkol 4 === Vytvořte funkci, které je předán jako parametr seznam čísel. Funkce v seznamu nalezne nejmensi cislo a vrati jeho index (pozici). cisla = [7, 6, 5, 8] i = nejmensi(cisla) x = cisla[i] print(x) # vypise cislo 5 [[courses:pri-bootcamp:solutions#Den 4 - Funkce - Úkol 4|Řešení]] ---- === Úkol 5 === Použijte funkci nejmensi() z předchozího úkolu a vytvorte funkci serad(), které je předán jako parametr seznam čísel. Funkce čísla v seznamu seřadí od nejmenšího po největší. [[courses:pri-bootcamp:solutions#Den 4 - Funkce - Úkol 5|Řešení]] ---- ===== Volitelné úkoly ===== ==== Rekurze ==== //“To iterate is human, to recurse divine.”// (L. Peter Deutsch)´ Nejjednodušší případ rekurzivní funkce, je taková funkce, která musí k vypočítání výsledku **zavolat sebe sama**. Například: def odecitej(x): return odecitej(x-1) Pokud vám stále ještě není jasné co je to rekurze, přečtěte si tuto větu ještě jednou... ;-) Funkce **odecitej** má ale jednu malou vadu. Nikdy nevrátí výsledek. Proto je potřeba mít v každé rekurzivní funkci takzvaný "**base case**", který ukončí rekurzivní volání. def odecitej_do_nuly(x): if x == 0: # base case return 0 # konec rekurze return odecitej_do_nuly(x-1) Funkce **odecitej_do_nuly** má stále ještě jeden problém. Odhalíte jaký? ---- ==== Úkoly ==== Při řešení následujících úkolů nesmíte použít klíčová slova __for__ ani __while__! ---- === Úkol 1 === Vytvořte pole obsahujicí deset náhodných čísel pomocí rekurze. [[courses:pri-bootcamp:solutions#Den 4 - Volitelný úkol 1|Řešení]] ---- === Úkol 2 === Naimplementujte funkci **faktorial(x)**, která vypočítá **x!** pomocí rekurze. [[courses:pri-bootcamp:solutions#Den 4 - Volitelný úkol 2|Řešení]] ---- === Úkol 3 === Napiště funkci **fibonacci(x)**, která vrátí x-tý prvek fibonacciho posloupnosti. [[courses:pri-bootcamp:solutions#Den 4 - Volitelný úkol 3|Řešení]] ---- === Úkol 4 === Vytvořte matici (2D pole) 5x5. matice = [ # matice 2x2 [1,2], [3,4], ] matice[1][1] # vrati 4 matice[0][1] # vrati 2 Vyplňte tuto matici čísly od 24 do 0 funkcí **jméno_funkce(matice)**, a poté vypište matici na standartní výstup. [[24, 23, 22, 21, 20], [19, 18, 17, 16, 15], [14, 13, 12, 11, 10], [9, 8, 7, 6, 5], [4, 3, 2, 1, 0]] [[courses:pri-bootcamp:solutions#Den 4 - Volitelný úkol 4|Řešení]] ---- === Úkol 5 (Náročnější!) === Máte šachové pole 9x9 a figurku jezdce na pozici (4,4). Označte všechny políčka šachovnice, na které jezdec může doskákat do tří tahů, hodnotou 1 a ostatní políčka hodnotou nula. Vypiště šachovnici na standartní výstup. Jezdec nemusí využít všechny své tahy. K vypsání můžete použít for cyklus. Výstup programu: 001010100 010101010 100111001 011101110 101010101 011101110 100111001 010101010 001010100 Stav sachovnice po jednotlivých tazích (namísto 0 a 1 jsou zde kvůli názornosti použité mezery a znak 'X'): # prvni tah # druhy tah # treti tah | | | | | X X X | | | | | | X X X X | | | | X X | |X XXX X| | | | X X | | XXX XXX | | X | -> | X | -> |X X X X X| | | | X X | | XXX XXX | | | | X X | |X XXX X| | | | | | X X X X | | | | | | X X X | [[courses:pri-bootcamp:solutions#Den 4 - Volitelný úkol 5|Řešení]] ---- == Úkol 6 (oddechový) == Choose you favourite [[http://www.devtopics.com/101-great-computer-programming-quotes/|Computer Quote]] 8-) ----