====== Vejce ====== Určete nejvyšší patro, z něhož můžete vejce ještě hodit, aby se nerozbilo! ^ Prerekvizity | Základní znalost Pythonu | ^ Náročnost přemýšlení | Střední | ^ Náročnost programování | Střední | ===== Úloha ===== Chceme vytvořit algoritmus pro určení pevnosti daného typu vajec. Všechna vejce mají stejnou pevnost. Pevnost vajec měříme tak, že je pouštíme z paneláku z různých pater. Pevnost vejce je definována jako číslo nejvyššího patra, z něhož můžete vejce pustit, aby se ještě nerozbilo. Pokud je P pevnost vejce, pak pustíte-li ho z patra číslo P nebo nižšího, vejce se nerozbije (a můžete ho použít pro další test); pustíte-li ho z patra P+1 nebo vyššího, vejce se rozbije (a znovu ho už použít nemůžete). Pokud se vejce rozbije už při pádu z prvního patra, je P = 0. Pokud má panelák N pater, je nejvyšší možná pevnost vajec P = N. Vstupem algoritmu by měla být výška paneláku (tj. největší pevnost vejce, kterou můžete "změřit") a počet vajec, která máte k dispozici pro experimenty (a nevadí nám, že se při experimentech rozbijí). S daným počtem vajec by měl algoritmus určit pevnost vajec co nejrychleji, tj. s co nejmenším počtem hodů vejce z paneláku. Zkuste si rozmyslet: * Jak byste postupovali, kdybyste měli k dispozici jediné vejce? * Jak byste postupovali, kdybyste měli k dispozici vajec, kolik chcete? * Jak byste postupovali, kdybyste měli k dispozici 2, 3, ... vejce? ===== Specifikace ===== Vaším úkolem je naprogramovat strategii experimentu, tedy algoritmus, který bude postupně volit patra, z nichž chcete pouštět vejce, v závislosti na tom, zda vejce předchozí test "přežilo" nebo ne. V modulu ''solver.py'' vytvořte funkci ''determine_egg_strength()'', s následujícími vstupy a výstupy: ^ Vstupy | ''n_floors'' | Celé kladné číslo. Výška (počet pater) paneláku neboli maximální měřitelná pevnost vejce. | ^ | ''n_eggs'' | Celé kladné číslo. Počet vajec, která máte k dispozici. Pokud se dostanete do situace, že pevnost vejce ještě neznáte a nemáte už žádné vejce, je to špatně. | ^ | ''egg_survives_floor'' | Funkce. Simuluje jeden test, tedy upuštění vejce z nějakého patra. Vrací ''True'', resp. ''False'', pokud vejce pád z daného patra přežilo, resp. nepřežilo. | ^ Výstupy | ''strength'' | Celé číslo. Pevnost vejce. | ===== Příklad ===== Funkce ''egg_survives_floor()'' simuluje upuštění vejce z jistého patra. Může být definována např. takto: def egg_survives_floor(floor): return floor <= 18 Tato funkce odpovídá tomu, že pevnost vejce je 18. Váš algoritmus samozřejmě toto číslo nebude znát, může jen volat funkci ''egg_survives_floor'' a zjišťovat tak, zda vejce pád přežilo nebo ne. Asi nejjednodušším algoritmem, který danou úlohu řeší, je postup, kdy budete postupovat od nejnižšího patra k nejvyššímu, dokud se vejce nerozbije. Takové řešení může vypadat třeba takto: def determine_egg_strength(n_floors, n_eggs, egg_survives_floor): for floor in range(n_floors): if not egg_survives_floor(floor+1): return floor return n_floors Pokud tuto funkci zavoláme s výše definovanou funkcí ''egg_survives_floor()'', dostaneme očekávaný výsledek: >>> determine_egg_strength(30, 10, egg_survives_floor) 18 Toto řešení je validní, vždy najde správnou pevnost vejce a potřebuje vždy jen jedno vejce. Zároveň ale tato strategie není nejlepší, protože nevyužila všechna vejce, které měla k dispozici pro experiment. Lze postupovat mnohem chytřeji! ===== Hodnocení ===== * Váš algoritmus bude otestován na sadě testovacích případů. * Jeden testovací případ je dvojice hodnot ''n_floors, n_eggs''. * Pokud dojde při kterémkoli testu k chybě, získáte 0 bodů. * Pro každý testovací případ bude váš algoritmus otestován pro všechny možné pevnosti vajec 0, ..., ''n_floors'', a zaznamená se dílčí skóre - nejvyšší počet testů, který jste potřebovali k určení pevnosti vejce. * Skóre vaší strategie je pak součet dílčích skóre přes všechny testovací případy. * Vaše skóre se pak porovná se skóre triviálního algoritmu výše a optimálního algoritmu a na základě toho bude určen poměrný počet bodů. Příklad hodnocení triviálního algoritmu: * Předpokládejme, že sada testovacích případů je ''( (5, 1), (10, 2), (20, 3) )''. * Výše uvedený triviální algoritmus * pro testovací případ ''(5,1)'' a pro pevnost vejce 1 potřebuje 1 hod, pro pevnost vejce 2 potřebuje 2 hody, ... pro pevnost vejce 5 potřebuje 5 hodů, takže jeho dílčí skóre je 5, * pro testovací případ ''(10, 2)'' a pro pevnost vejce 1 potřebuje 1 hod, ... pro pevnost vejce 10 potřebuje 10 hodů, takže jeho dílčí skóre je 10, * pro testovací případ ''(20, 3)'' ... má dílčí skóre 20. * Celkové skóre vašeho algoritmu tak je 20 + 10 + 5 = 35.