Autorské riešenie
Pri tejto úlohe je potrebné si uvedomiť, že úloha nie je vždy riešiteľná.
V prípade neriešiteľnosti úlohy je dobré upozorniť používateľa vyhodením výnimky.
Pozrime sa na jednotlivé prípady, kedy úloha nemá riešenie a
ako riešenie nájsť, ak úloha rieŠenie má. Ak Jožko doteraz nedostal žiadne známky, ale nejaké známky ešte dostane, tak dostane všetky známky rovnakej hodnoty, ako je požadovaná známka. Aby Jožko mohol dostať požadovanú celkovú známku, tak pre celkový priemer (priemer zo známok ktoré už má a ktoré ešte dostane) musí platiť: (1) požadovaná známka - 0.5 <= celkový priemer < požadovaná znamka + 0.5 Označme si:
Z týchto hodnôt si vyjadrime celkový priemer: (2) celkovy_priemer = (sucet_m + sucet_n) / (pocet_m + pocet_n) a priemer nových známok: (3) priemer_nove = (sucet_n / pocet_n) Ak takto vyjadrené priemery dosadíme do vzťahu (1), môžeme si vyjadriť, aký minimálny a maximálny priemer môžu mať známky, ktoré Jožko ešte dostane: ((z - 0.5) * (pocet_m + pocet_n) - sucet_m) / pocet_n
<= priemer_nove Zároveň ale musí platiť: 1 <= priemer_nove <= 5, teda: ((z - 0.5) *
(pocet_m + pocet_n) - sucet_m) / pocet_n <= 5 Tieto vzťahy definujú ďalšie podmienky riešiteľnosti. Ak pre zadané parametre je úloha riešiteľné, vytvorme zoznam najhorších možných známok. Vytvoríme zoznam nových známok nasledovne:
Výsledná funkcia nove_znamky() môže vyzerať nasledovne: #Python import math def priemer(znamky): ''' Výpočet priemeru známok zo zoznamu. :param znamky: zoznam známok, z ktorých je počítaný priemer :type znamky: list ''' if len(znamky) == 0: return 0 return sum(znamky) / len(znamky) def nove_znamky(znamky, pocet_novych_znamok, pozadovana_znamka): ''' Zistenie známok, ktoré môže dostať. :param znamky: zoznam známok, ktoré už dostal :type znamky: list :param pocet_novych_znamok: počet známok, ktoré ešte dostane :type pocet_novych_znamok: int :param pozadovana_znamka: výsledná známka, ktorú chce dostať :type pozadovana_znamka: int ''' # Jozko ziadne znamky este nedostal a ani nedostane if len(znamky) == 0 and pocet_novych_znamok == 0: raise ValueError( "Žiadne známky, požadovanú známku nie je možné dosiahnuť.") # Jozko ziadne znamky este nedostal ale nejake este dostane if len(znamky) == 0: return [pozadovana_znamka] * pocet_novych_znamok # Jozko uz ziadne znamky nedostane if pocet_novych_znamok == 0: priemer_starych_znamok = round(priemer(znamky), 0) if priemer_starych_znamok == pozadovana_znamka: return [] else: raise ValueError("Požadovanú známku nie je možné dosiahnuť.") # Jozko nejake znamky dostal a nejake este dostane priemer_nove_min = ((pozadovana_znamka - 0.5) * (len(znamky) + pocet_novych_znamok) - sum(znamky)) / \ pocet_novych_znamok priemer_nove_max = ((pozadovana_znamka + 0.5) * (len(znamky) + pocet_novych_znamok) - sum(znamky)) / \ pocet_novych_znamok # overime, ci je mozne dostat znamky s pozadovanym priemerom if priemer_nove_min > 5: raise ValueError("Požadovanú známku nie je možné dosiahnuť.") if priemer_nove_max <= 1: raise ValueError("Požadovanú známku nie je možné dosiahnuť.") nova_znamka = min(math.ceil(priemer_nove_max) - 1, 5) # ak by nove znamky boli len 5, nemame uz co zhorsovat if nova_znamka == 5: return [5] * pocet_novych_znamok # postupne zhorsujeme jednotlive znamky nove_znamky = [nova_znamka] * pocet_novych_znamok for i in range(pocet_novych_znamok): nove_znamky[i] += 1 if priemer(nove_znamky) >= priemer_nove_max: nove_znamky[i] -= 1 break return nove_znamky Funkcia nove_znamky() má 3 parametre:
Táto funkcia vráti zoznam známok, ktoré môže Jožko ešte dostať tak, aby ešte stále dostal požadovanú celkovú známku a rozdiely medzi známkami, ktoré dostane, sú minimálne. Vaše zaujímavé riešenia a najčastejšie chyby Najväčším problémom bolo odhalenie prípadov, kedy je úloha neriešiteľná. Prípady neriešitešnosti sú popísané vyššie v popise riešenia. |
||||||||||
© Univerzita Pavla Jozefa Šafárika v Košiciach, Prírodovedecká fakulta, Ústav informatiky palmaj (zavinac) upjs.sk |