====== Cvičení 3: Funkce ====== ==== Opakování cyklů ==== === Ramanujan Taxi === * [[https://cs.wikipedia.org/wiki/Srinivasa_Ramanujan|Ramanujan]] (1887-1920) byl velmi zajímavý geniální indický matematik. Byl objeven prof. Hardym a pozván do Anglie. Zde onemocněl a když ho prof. Hardy navštívil v nemocnici, řekl mu, že za ním přijel taxíkem číslo XXXX. Ramanujan mu okamžitě odpověděl, že je to velmi zajímavé číslo, protože je to nejmenší číslo, které lze zapsat dvěma různými způsoby jako součet dvou krychlí (třetích mocnin přirozených čísel). * Najděte čtyřciferné číslo taxíku XXXX. ==== Funkce ==== Při programování často potřebujeme vykonat určité operace opakovaně. K tomu se hodí tzv. funkce. * Funkce je seskupení příkazů * Vstupem funkce jsou argumenty (jsou nepovinné) * Složitý problém se typicky rozdělí na jednodušší úkony, které se naprogramují do funkcí * Takový kód je snáze udržovatelný/čitelný * Funkce mohou obsahovat lokální proměnné, které "nejsou vidět" ve zbytku programu * V Pythonu se funkce definují klíčovým slovem ''def'' a tělo funkce (vnitřní příkazy) jsou odsazeny def jmenoFunkce( parametry ): telo_funkce Maximum ze dvou čísel: def maximum(x,y): if x>y: return x else: return y * klíčové slovo ''return'' vrací výsledek funkce. Příklad volání této funkce: max = maximum(2,0.5) print(max) # nebo rovnou muzeme predat jiné funkci a = 6 b = 7 print("Maximum z ",a," a ", b, " je ", maximum(a,b)) * Parametry jsou nepovinné. Funkci bez parametrů definmujeme s prázdnými závorkami def hello(): print("Hello World!") * V tomto případě funkce ani nevrací žádnou hodnotu (pouze vypíše řetězec), není tedy třeba volat ''return'' * Volání funkce bez parametrů hello() * Funkce v Pythonu mohou vracet více parametrů * Příklad: funkce vracející maximum ze dvou čísel, s informací o tom, jestli maximem je 1. nebo 2. argument def maximum2(x,y): if (x > y): return x, True else: return y, False * Volání maxValue, info = maximum2(5,6) #zkusime predat printu: print("Maximum z 5,6 je ", maximum2(5,6)) === Funkce quit() === * Pokud není uvedeno jinak, program končí po vykonání posledního příkazu * Někdy se hodní ukončit program dříve, např. při špatně zadaném vstupu. * K tomu slouží funkce ''quit()'' if (spatny_vstup): quit() === Dosud jsme se setkali s několika funkcemi: === * ''input()'' - načte řetězec ze standardního vstupu * ''print( argumenty )'' - tiskne řetězec na standardní výstup * ''int( argument )'' - převod na celé číslo * ''float( argument )'' - převod na reálné číslo * ''str( argument )'' - převod na řetězec * ''quit()'' - ukončí běh programu ==== Úkol 1: absolutní hodnota ==== * Napište funkci s jedním argumentem, která vrací absolutní hodnotu tohoto argumentu ==== Úkol 2: Sexy prvočísla ==== * [[https://en.wikipedia.org/wiki/Sexy_prime|Sexy prime]] jsou takové dvojice prvočísel, jejichž (kladný) rozdíl je 6. Například 5 a 11 jsou prvočísla a zároveň se liší o 6, tedy dvojice (5,11) jsou tzv. sexy-primes. * Napište program, který vypíše všechny takové dvojice menší než 1000. ==== Úkol 3: Dokonalá čísla ==== * [[https://en.wikipedia.org/wiki/Perfect_number|Dokonalé číslo]] je takové číslo, které je součtem všech svých dělitelů (kromě sebe samotného samozřejmě). * Například číslo 6 je dokonalé, neboť 6 = 1 + 2 + 3, kde 1,2,3 jsou dělitelé čísla 6. * Napište program, který vypíše všechna dokonalá čísla od 1 do 10000. ==== Úkol 4: Super-dokonalá čísla ==== * [[https://en.wikipedia.org/wiki/Superperfect_number|Super-dokonalá čísla]] jsou zobecněním dokonalých čísel. * Číslo $n$ je super-dokonalé, pokud platí $f(f(n)) = 2n$, kde $f(n)$ je součet dělitelů čísla $n$ od 1 do $n$ (včetně $n$). * Například pro číslo 4: dělitelé jsou $1,2$ a $4$, tedy $f(4)=1+2+4=7$. Dělitelé 7 jsou 1 a 7, tedy $f(7)=1+7=8$, což je $2\times4$. Číslo 4 je tedy super-dokonalé. * Napište funkci ''soucet_delitelu'', která spočte součet dělitelů čísla $n$, tedy funkci $f(n)$. * Funkci ''soucet_delitelu'' použijte v programu, který vypíše seznam super-dokonalých čísel od 1 do 10000. ==== Úkol 5: Největší společný dělitel ==== * Napište funkce ''gcd1(a,b)'' a ''gcd2(a,b)'', které vrátí největšího společného dělitele čísel $a$ a $b$. * Funkce gcd1 bude počítat největšího společného dělitele čísel $a$ a $b$ takto: * Dokud a není rovno b * Je-li a větší než b * a = a-b * jinak * b = b-a * a i b jsou největší společný dělitel původních čísel * Funkce gcd2 bude počítat největšího společného dělitele čísel následovně: * Dokud b není rovno nule * t = b * b = a mod b * a = t * a je největší společný dělitel původních čísel * Zjistěte kolik kroků potřebuje gcd1 a gcd2 pro spočtení největšího společného dělitele 6997193,18992381 a dvojice 361,18992381 ==== Úkol 6 Césarova šifra ==== * Napište program pro realizaci tzv. Césarovy šifry * Vstup: dvě řádky * 1. řádka: textový řetězec (pouze písmena a mezery) * 2. řádka: číslo definující posunutí písmen v Césarově šifře * Program na výstup vypíše vstupní řetězec zašifrovaný posunutím písmen o zadanou hodnotu * Ascii hodnota znaku se získá funkcí ''ord('A')'', opačně znak z celého čísla získáte funkcí ''chr(65)'' * Je nutné posouvat velká písmena na velká písmena, malá písmena na malá písmena a mezeru ponechat jako mezeru ==== Úkol 7 Převod měsíců ==== * Napište funkci ''convert_num_to_month'', která dostane jako parametr pořadové číslo měsíce v roku a vrátí jeho jméno. * Napište funkci ''convert_month_to_num'', která dostane jako parametr jméno měsíce v roku a vrátí jeho pořadové číslo v roce. * Předpoklad: leden má číslo 1, prosinec 12 * Tuto funkci použijte v programu, který načte řetězec * Pokud je první znak písmeno, vytiskne se na obrazovku číslo měsíce * Pokud je první znak číslo vytiskne se název měsíce * Pomůcka: V programu můžete využít následující proměnnou: month=['leden','unor','brezen','duben','kveten','cerven','cervenec','srpen','zari','rijen','listopad','prosinec'] ===== Témata k procvičení ===== * Napište funkci, která vypisuje 1,-1,1,-1 ... * Napište funkci, která vypisuje výsledek operace $(-1)^k$ pro $k=0,\ldots,100$. Zamyslete se nad rychlostem výpočtu, navrhněte alternativní postupy * Napište funkci ''min(a,b)'', která vrací minimum z těchto dvou prvků (proměnné jsou čísla). * Napište funkci ''max(a,b)'' * Napište funkci ''area(radius)'', která vypočítá obsah kruhu o zadaném poloměru * Napište funkci ''d2r(angle)'', která převede stupně na radiány "degrees to radians = d2r" * Napište funkci ''r2d(angle)'', která převede radiány na stupně * Napište funkci ''normalize(angle)'', která převede zadaný úhel (v radiánech) do intervalu $<0, 2\pi)$ * Napište funkci pro výpis pole: * s využitím cyklu ''for'' * s využitím cyklu ''while'' * Rozšiřte program na výpočet Sexy-prvočísel tak, aby vypisoval trojice prvočísel, které se od sebe liší o 6 - taková trojice je např. (5,11,17). * Dále rozšiřte tento program pro výpočet čtveřic (např. (61,67,73,79) ). ===== Domácí úkol ===== ==== Lehká varianta ==== * Text zakódovaný Caesar-Euklidovou šifrou * Vstup: * první řádka obsahuje počet znaků zakódovaného textu * ostatní řádky obsahují vždy dvojici celých čísel a,b. Znak je určen jako největší společný dělitel čísel a, b, který určuje kód tohoto znaku. * Výstup: * jedna řádka, která obsahuje zakódovaný text * znak z celého čísla ''x'' získáte funkcí ''chr(x)'' * Program pro úlohu **HW03** pojmenujte **caesar.py** Např. pro vstup 3 4484386 5430482 997155 6818895 2444051 6275419 vypadá výsledek takto: :-) pro vstup 9 1334386 13553534 3422019 12611931 8627474 6240422 12426219 12740481 13055039 7863151 9461235 9289245 12206332 15916244 6835579 14041121 3957597 11286009 vypadá výsledek takto: Rozumite? pro vstup 10 12994044 8108268 14877663 11703507 1093472 1825888 4053122 8115466 17435933 18487747 1926688 904864 17461286 15207014 19130135 15972695 15720953 4226951 3450782 91862 vypadá výsledek takto: To je vse. ==== Těžká varianta ==== * Napište program **date.py**, který převádí mezi číselnou reprezentací data a mezi slovní reprezentací data v angličtině. * **Vstup:** řetězec ze standardního vstupu * Tento řetězec buď obsahuje datum zadané čísly v desítkové soustavě, např.1.11.1958 * nebo datum zapsané anglicky slovy, např.the first of November onethousandninehundredfiftyeight * **Výstup:** řetězec na standardní výstup * tento řetězec obsahuje vstup převedený do opačného zápisu, tj. text na číslo, nebo číslo na text. * pokud vstup není ani číselný, ani slovní popis platného datumu, pak je výstup ''ERROR'' * Všechny roky jsou v rozsahu 1-9999 a píšeme je stejně jako jejich číselné hodnoty. * Datum text začíná určitým členem ''the'', pak následuje řadová číslovka, pak slovo ''of'' a číslo reprezentující rok * Datum reprezentovaný číslem, obsahuje číslo dne, znak ''.'', číslo reprezentující měsíc, znak ''.'', číslo reprezentující rok * Rok píšeme s použitím thousand, nebudeme používat rozdělení na sta. * Pro textovou reprezentaci čísel použijte pouze spojení následujících slov: * ''the, first, second, third, th, fifth, eighth, ninth, twelfth, twentieth, thirtieth, of, January, February, March, April, May, June, July, August, September, October, November, December, one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen, fourteen, fifteen, sixteen, seventeen, eighteen, nineteen, twenty, thirty, forty, fifty, sixty, seventy, eighty, ninety, hundred, thousand''. * Vypisujte i úvodní jedničku, tj. pro vstup ''1000'' vypište ''onethousand'', podobně pro ''120'' se očekává výstup ''onehundredtwenty'' * Pro únor předpokládejte, že může mít 29 dní (neověřujte, že jde o přestupný rok) * Snažte se napsat program elegantně, je možné složit číslo z jeho součástí při převodu v obou směrech * **Hodnocení** - Program umí převádět validní vstupy v obou směrech **[1.5b]** * Vstup: 31.12.3219 Výstup: the thirty-first of December threethousandtwohundrednineteen * Vstup: the twenty-ninth of February onethousandtwohundredthirtyfour Výstup: 29.2.1234 - Program **navíc** umí detekovat chybné vstupy **[0.5b]** * Vstup: 2.9.5.1234 Výstup: ERROR * Vstup: the fivetwentieth of January twenty Výstup: ERROR * Vstup: the twentieth of January twentyten Výstup: ERROR