====== Dilema I ======
[[courses:b4b33rph:internal:cviceni:program_po_tydnech:tyden_02|Učitelská verze stránky]]
===== Výsledky učení =====
Po tomto cvičení student
* chápe zadání úlohy Vězňovo dilema a rozumí, jakým způsobem bude jeho hráč testován,
* využívá ''for'' cyklus k implementaci jednoduchých opakujících se činností,
* je si vědom, že je třeba kódy testovat,
* implementuje jednoduché vlastní datové typy pomocí tříd,
* chápe funkci ''__dunder__'' metod a není překvapen, když je vidí.
===== Program =====
* diskuse problémů
* diskuse prvního DÚ s Lenkou
* vyjasnění zadání úlohy Vězňovo dilema
* procvičování ''for'' cyklů
* třída pro komplexní čísla a jejich sčítání, násobení, ...
* procvičování základních datových typů
===== Hádanka ======
/* Pro vyplnění formuláře je třeba se přihlásit na Google pod Vaší FEL identitou
[[https://forms.gle/kFqxMq54p7hjByPu6|101]]
[[https://forms.gle/3nLTaoxHoVa3zQVk7|102]]
[[https://forms.gle/QaZvFUtncp1Ne1CH7|103]]
[[https://forms.gle/vzsGD3QyLgcqMk1g7|104]]
[[https://forms.gle/oMqTMgeh4ao4uiwL8|105]]
[[https://forms.gle/uyin2XUR2RuBFCna6|106]]
[[https://forms.gle/MuffuZrZW4u4wWx8A|107]]
[[https://forms.gle/4kfZisGQAbhkvdvHA|108]]
[[https://forms.gle/yARdGc2Gxtt5qAudA|109]]
*/
Zadání hádanky se dozvíte na cvičení.
===== Lenka =====
* Je všem jasné, jaké pořadí odpovědí bylo správné?
* Proč jste pro své řešení volili malá/velká písmena?
* Odpovědi velkými písmeny získávají svou odměnu jen v případě, že procento odpovědí velkými písmeny přesáhne jistý práh. Pro jakou hodnotu prahu se pro vás osobně láme rozhodnutí mezi velkými a malými písmeny?
===== Vězňovo dilema =====
Na přednášce byl prezentován problém vězňova dilematu. Přečtěte si pozorně zadání úlohy: [[..:veznovo_dilema:start| Vězňovo dilema]]. Ptejte se na nejasnosti.
==== Jak splnit zadání úlohy ====
Několik základních kontrolních bodů, kterých je rozumné se držet:
* správně pojmenovat soubor
* správně pojmenovat funkce, třídy a metody (pozor na malá a velká písmena), které jsou požadovány ve specifikacích
* správné parametry metody (self)!
* výstup metody
* správné odsazení
* nepřepisovat vnitřní proměnné nebo funkce Pythonu
==== Další známé hry ====
Další hry ala vězňovo dilema pro vaši inspiraci:
* [[http://en.wikipedia.org/wiki/Rock,_Paper,_Scissors|Rock paper scissors]]
* [[http://en.wikipedia.org/wiki/Chicken_(game)|Game of chicken]]
* [[http://en.wikipedia.org/wiki/Matching_pennies|Matching pennies]]
* [[http://en.wikipedia.org/wiki/Coordination_game|Coordination game]]
* [[http://en.wikipedia.org/wiki/Ultimatum_game|Ultimatum game]]
* [[http://en.wikipedia.org/wiki/Pirate_game|Pirate game]]
====== Úkoly na cvičení ======
===== For cykly =====
==== Seznam a jeho procházení ====
- Vytvořte proměnnou ''years'' obsahující seznam několika letopočtů, které jsou pro vás něčím významné, např. roky narození vašich blízkých.
- Zjistěte, kolik prvků seznam obsahuje. Jakou funkci Pythonu k tomu použijete?
- Vypište jednotlivé letopočty pomocí ''for''-cyklu, každý na jeden řádek. Jaké různé způsoby řešení této úlohy vás napadají?
- Upravte kód tak, aby se spolu s letopočtem vypisoval i index prvku v poli. Jaké různé způsoby řešení této úlohy vás napadají?
- Zkuste změnit hodnotu proměnné ''years'' tak, aby váš kód skončil chybou, nebo se choval z vašeho pohledu neočekávaně. Zkuste porozumět chybové hlášce/důvodu, proč se kód chová právě takto. K porozumění/vysvětlení můžete využít dokumentaci k Pythonu, internetová fóra, i umělou inteligenci.
==== Funkce pracující se seznamem ====
- Doplňte implementaci následující funkce pro nalezení největšího prvku v kolekci. Je funkce dostatečně specifikovaná? Co ještě potřebujete vědět?
def find_max(collection):
"""
Return a tuple: the maximum item found in the collection, and its index
"""
- Opět, zkuste změnit hodnotu proměnné ''years'' tak, aby funkce ''find_max'' selhala nebo vrátila nečekaný výsledek.
- Vytvořte obdobnou funkci ''find_all_max(collection)'', která nebude vracet jen jeden index maximálního prvku, ale seznam indexů všech výskytů maximálního prvku.
===== Datové typy =====
==== Základní datové typy Pythonu ====
* Jaké základní datové typy Python obsahuje? ++ Typy: | celá a desetinná čísla, řetězce, pravdivostní hodnoty (True/False)++
* Co když chcete vytvořit vlastní složený datový typ?
===== Jednoduchá třída =====
Navrhněte a implementujte třídu ''ComplexNumber''.
==== K rozmyšlení ====
- Čím je instance komplexního čísla definována? Jaké bude mít členské proměnné?
- Jaké má vlastnosti?
- Jaké má schopnosti? Jaké operace lze dělat s komplexním číslem?
==== Implementace ====
Pokuste se třídu implementovat a postupně rozšiřujte její schopnosti. Neděste se, vyučující vám na cvičení ukáží jak na to.
* ++ Inicializace | Implementujte metodu ''__init__(self, re, im)''. Co vidíte při spuštění příkazů:
>>> a = ComplexNumber(3,4)
>>> print(a.re)
>>> print(a.im)
>>> print(a)++
* ++ Čitelná reprezentace | Nebylo by hezké, kdyby instance komplexního čísla uměla vytvořit hezky čitelnou řetězcovou reprezentaci? Implementujte metodu ''to_string(self)'' tak, aby kód fungoval takto:
>>> a = ComplexNumber(3,4)
>>> print(a.to_string())
3+4i++
* ++ Absolutní hodnota komp. čísla | Implementujte metodu ''abs(self)'', která vypočte a vrátí absolutní hodnotu komplexního čísla:
>>> a = ComplexNumber(3,4)
>>> print(a.abs())
5++
* ++ Inkrement reálné a imaginární části | Implementujte metodu ''inc_parts(self, re, im)'', která zvětší hodnoty reálné a imaginární části o zadaná čísla:
>>> a = ComplexNumber(1,2)
>>> a.inc_parts(2,2)
>>> print(a.to_string())
3+4i++
* ++ Inkrement komp. čísla jiným komplexním číslem | Implementujte metodu ''inc(self, other)'', která zvětší hodnoty reálné a imaginární části o hodnoty reálné a imaginární části druhého komplexního čísla předaného jako argument:
>>> a = ComplexNumber(1,2)
>>> b = ComplexNumber(2,2)
>>> a.inc(b)
>>> print(a.to_string())
3+4i++
* ++ Součet komplexních čísel | Implementujte metodu ''add(self, other)'', která sečte komplexní číslo ''self'' s komplexním číselm ''other'' a výsledek vrátí jako novou instanci komplexního čísla:
>>> a = ComplexNumber(1,2)
>>> b = ComplexNumber(2,2)
>>> c = a.add(b)
>>> print(c.to_string())
3+4i++
==== "Dunder" metody ====
Možnost hezky vypsat komplexní číslo, zjistit jeho velikost, nebo sečíst 2 komplexní čísla pomocí námi definovaných metod je šikovná, ale ještě šikovnější by bylo, kdybychom mohli
* místo ''print(a.to_string())'' napsat prostě ''print(a)'',
* místo ''a.abs()'' využít funkci ''abs(a)'', což je obvyklý způsob, jak zjistit absolutní hodnotu tam, kde to dává smysl, nebo
* místo ''a.add(b)'' psát prostě ''a+b''.
Python k tomu nabízí prostředky ve formě tzv. [[https://www.geeksforgeeks.org/dunder-magic-methods-python/|dunder metod]] (double underscore), kterým se taky někdy říká //magické metody//, ale nic magického na nich není (viz též [[https://docs.python.org/3/reference/datamodel.html#special-method-names|oficiální dokumentace]]). Jsou to metody, které se obvykle nevolají přímo, ale volá je interpret Python v jistých situacích. Jednu z nich už jste poznali - metodu ''__init__()'', kterou Python volá po vytvoření nové instance nějaké třídy a jejímž úkolem je instanci inicializovat.
Pokuste se naši třídu ''ComplexNumber'' vybavit těmito metodami:
* ++ __str__(self) | Buď přejmenujte metodu ''to_string()'' nebo ji v metodě ''__str__'' zavolejte. Měl by pak fungovat následující kód:
>>> a = ComplexNumber(3,4)
>>> print(a)
3+4i++
* ++ __abs__(self) | Buď přejmenujte metodu ''abs(self)'' nebo ji v metodě ''__abs__'' zavolejte. Měl by pak fungovat následující kód:
>>> a = ComplexNumber(3,4)
>>> print(abs(a))
5++
* ++ __add__(self, other) | Buď přejmenujte metodu ''add(self, other)'' nebo ji v metodě ''__add__'' zavolejte. Měl by pak fungovat následující kód:
>>> a = ComplexNumber(1,2)
>>> b = ComplexNumber(2,2)
>>> c = a + b
>>> print(c)
3+4i++
* Dokážete nyní odhadnout, k čemu slouží metoda ''__mul__(self, other)'' a pro jaký kód ji Python zavolá? Uměli byste tuto metodu implementovat pro třídu ''ComplexNumber''? Zkuste to, není to nic těžkého.
* Když umíme dvě komplexní čísla sečíst, umíme je i odečíst, nebo ne? Zkuste, co udělá následující kód:
>>> a = ComplexNumber(1,2)
>>> b = ComplexNumber(2,2)
>>> c = a - b
>>> print(c)Dokážete třídu upravit tak, aby tento kód fungoval?
====== Domácí úkol ======
===== Skalární součin vektorů =====
* Vytvořte modul ''vectors.py''.
* V něm bude definice třídy ''MyVector''.
* Konstruktor bude akceptovat (navíc k ''self'') jeden parametr, kterým bude seznam s prvky vektoru.
* Metoda ''get_vector(self)'' navrátí seznam obsahující prvky vektoru.
* Pomocí metody ''__mul__(self, other)'' implementujte [[https://en.wikipedia.org/wiki/Dot_product|skalární součin]] dvou objektů typu ''MyVector''. Výstupem je tedy skalár (jedno číslo). V metodě počítejte s libovolnou délkou vektorů, oba budou stejné, ale libovolné délky (ne jen 3-dimenzionální).
* Neměli byste cítit potřebu importovat v modulu ''vectors.py'' jiné moduly (snad kromě modulu ''typing''). Požadovanou funkcionalitu máte implementovat sami, nikoli ji delegovat na nějaké jiné knihovny, které by práci udělali za vás.
* Soubor nahrajte do BRUTE do požadovaného termínu.
* BRUTE vám kód ihned ohodnotí, případně několik sekund počkejte.
* Za správně vyřešenou úlohu získáte až 2 body.
Nazapomeňte na vlastní kontrolu kódu, nespoléhejte pouze na kontrolu v BRUTE. Třeba něco jako:
if __name__ == "__main__":
vec1 = MyVector([1,2,3]) # vektory mohou byt i jine dimenze nez 3!
vec2 = MyVector([3,4,5])
print(vec1.get_vector()) # priklad ziskani seznamu
dot_product = vec1*vec2 # vypocet skalarniho soucinu, pretizeny operator *, vola se __mul__
print(dot_product) # jen kontrolni vypis
===== Čtení =====
Přečtěte zbytek vašeho vybraného Python tutorialu ({[b4b33rph:Kubias2008]} nebo [[https://naucse.python.cz/course/pyladies/|Nauč se Python!]]). Nemusíte úplně rozumět všemu, ani si pamatovat vše zpaměti. Měli byste mít natrénován postup jak si dohledat potřebné informace, mít natrénovanu práci s např. [[http://docs.python.org/py3k/tutorial/index.html|Python 3 tutoriálem]], nebo jiným podobným zdrojem veškeré moudrosti ;-)
===== Interaktivní cvičení =====
Na //codecademy// pokračujte v [[https://www.codecademy.com/learn/learn-python|interaktivním kurzu Pythonu 2]] nebo [[https://www.codecademy.com/learn/learn-python-3|Pythonu 3]], pokud k němu máte přístup. Předpokládáme, že otázky, které jste měli po části kurzu z minulého týdne, jste položili na fóru nebo právě dnes na cvičení a že tudíž můžete pokračovat dál sekcemi:
* Functions
* Taking a vacation
* Python lists and dictionaries
* A day at the supermarket
* Student becomes the teacher
* Lists and functions
* Loops
Opět se pokuste dostat co nejdál. Stále platí, že tato cvičení vám mají především pomoci **identifikovat věci, kterým nerozumíte**. **Pokládejte otázky na Discordu, na fóru nebo na cvičení!**