Autorské riešenie
[stiahni py]                                       

  • Počet riešiteľov: 11 / 15 = 73 %

  • Úspešnosť riešenia: 4,45 / 8 = 56 %                   

Pri riešení úlohy pracujeme s premennou zaznamy_pretekov, ktorej hodnoty vygeneroval už preddefinovaný generátor záznamov Preteky. Parametrami tohto generátora sú hodnoty reprezentujúce počet kontrol a počet pretekárov. Tento generátor nám umožňuje testovať náš program pre rôzne situácie.

Premenná zaznamy_pretekov je prepojená so zoznamom, ktorý obsahuje záznamy jednotlivých pretekárov zo všetkých kontrol, ktoré navštívili. Tieto záznamy sú opäť zoznamy, každý obsahuje trojicu údajov: číslo kontroly, registračné číslo pretekára a čas, v ktorom pretekár na danú kontrolu dorazil. Čas je reprezentovaný v podobe sekúnd, ktoré v danej chvíli uplynuli odo dňa narodenia zakladateľa pretekov.

Postup riešenia si rozdelíme na čiastkové kroky:

  1. získanie záznamov pre jednotlivých pretekárov
  2. výpočet výsledného času konkrétneho pretekára a jeho uloženie
    • kontrola záznamov pretekára, či prešiel všetky kontroly, kým dorazil do cieľa - ak áno, vypočítame výsledný čas,
    • ak pretekár nesplnil podmienky pretekov, výsledný čas nepočítame (hodnota None)
  3. výpis výsledkovej listiny

Prvý krok nášho riešenia sme vyriešili vo funkcii vyber_zaznamy_pretekara. Táto funkcia prechádza zoznam zaznamy_pretekov a hľadá záznamy pretekára s registračným číslom zhodným s hodnotou premennej pretekar. Takto získané záznamy ukladá do zoznamu zaznamy_pretekara a zároveň ich odstraňuje zo zoznamu zaznamy_pretekov.

Návratovou hodnotou funkcie vyber_zaznamy_pretekara je zoznam záznamov skúmaného pretekára, zároveň táto funkcia modifikuje zoznam zaznamy_pretekov tak, že z neho odstráni záznamy tohto pretekára. Získaný zoznam skúmaného pretekára je potrebné skontrolovať a rozhodnúť, či preteky absolvoval úspešne (môžeme počítať jeho výsledný čas) alebo bol diskvalifikovaný. Tento druhý krok riešenia sme vyriešili vo funkcii zisti_cas_pretekara.

Pracujeme so zoznamom zaznamy_pretekara (krorý sme získali v predchádzajúcom kroku) - usporiadame ho podľa času (aby sme "videli", v akom poradí pretekár navštevoval kontroly). Na kontrolu, či pretekár prešiel všetky kontroly kým prišiel do cieľa, použijeme premennú nenavstivene_kontroly. Ako už naznačuje jej názov, na začiatku bude tento zoznam obsahovať čísla všetkých kontrolných stanovíšť. Ak pretekár absolvoval konkrétnu kontrolu, odstránime jej číslo zo zoznamu nenavstivene_kontroly.

Vieme, že čas štartu je v prvej položke zoznamu. Uložíme ho do premennej cas_start. V cykle for prechádzame jednotlivé záznamy pretekára. Ak je to záznam z cieľa, skontrolujeme, či je zoznam nenavštívených kontrol prázdny. Ak áno, pretekár úspešne dorazil do cieľa a navštívil všetky kontroly medzi štartom a cieľom. Jeho výsledný čas vypočítame ako rozdiel času v cieli (aktuálny záznam, časový údaj je posledným prvkom zoznamu) a času na štarte. Tento údaj je návratovou hodnotou funkcie v prípade úspešného absolvovania preteku, inak je návratovou hodnotou None.

Tretím krokom riešenia je získanie a vypísanie výsledkovej listiny. Obidve spomínané funkcie vyber_zaznamy_pretekara a zisti_cas_pretekara sú volané funkciou vysledkova_listina. Výsledné časy úspešných pretekárov spolu s ich registračným číslom zhromažďujeme v premennej pretekari_casy, registračné čísla diskvalifikovaných pretekárov evidujeme v zozname diskvalifikovani.

Zoznam pretekari_casy usporiadame podľa výsledného času. Návratovou hodnotou funkcie je zoznam, ktorý vznikol spojením zoznamov úspešných a diskvalifikovaných pretekárov. Takto získaný zoznam vypíšeme v hlavnej časti zdrojového kódu.

#Python
def vyber_zaznamy_pretekara(zaznamy_pretekov, pretekar):
    zaznamy_pretekara = []
    index = 0
    while index < len(zaznamy_pretekov):
        if zaznamy_pretekov[index][1] == pretekar:
            zaznamy_pretekara.append(zaznamy_pretekov.pop(index))
        else:
            index += 1
    return zaznamy_pretekara


def zisti_cas_pretekara(zaznamy_pretekara, pocet_kontrol):
    zaznamy_pretekara.sort(key=lambda zaznam: zaznam[2])
    nenavstivene_kontroly = list(range(pocet_kontrol-1))
    cas_start = zaznamy_pretekara[0][2]
    for zaznam in zaznamy_pretekara:
        if zaznam[0] == pocet_kontrol - 1:
            if len(nenavstivene_kontroly) == 0:
                return zaznam[2] - cas_start
        else:
            if zaznam[0] in nenavstivene_kontroly:
                nenavstivene_kontroly.remove(zaznam[0])
    return None


def vysledkova_listina(zaznamy_pretekov, pocet_kontrol):
    pretekari_casy = []
    diskvalifikovani = []
    while len(zaznamy_pretekov) != 0:
        pretekar = zaznamy_pretekov[0][1]
        zaznamy_pretekara = vyber_zaznamy_pretekara(zaznamy_pretekov, pretekar)
        cas_pretekara = zisti_cas_pretekara(zaznamy_pretekara, pocet_kontrol)
        if cas_pretekara is None:
            diskvalifikovani.append([pretekar, 'diskvalifikovany'])
        else:
            pretekari_casy.append([pretekar, cas_pretekara])
    
    pretekari_casy.sort(key=lambda zaznam : zaznam[1])
    return pretekari_casy + diskvalifikovani


print(vysledkova_listina(zaznamy_pretekov, pocet_kontrol))
 

Vaše zaujímavé riešenia a najčastejšie chyby

Zaujímavé postupy riešenia sa objavili pri riešení prvého kroku riešenia:

  • usporiadanie záznamov pretekov podľa registračného čísla pretekára (tým dosiahneme "zoskupenie" záznamov jednotlivých pretekárov),
  • použitie slovníka, kde kľúčom je registračné číslo pretekára, hodnotami jeho záznamy.

Najčastejšie chyby:

  • nesprávne pochopenie časového údaja uvedeného pri každej kontrole,
  • nesprávna kontrola absolvovaných stanovíšť - pri nájdení záznamu s číslom cieľovej kontroly tím automaticky vzal čas tejto kontroly ako čas dosiahnutia cieľa bez ohľadu na to, či pretekár pred tým absolvoval všetky kontrolné stanovištia,
  • diskvalifikácia pretekára, ktorý splnil podmienky pretekov, ale po dosiahnutí cieľa sa ďalej pohyboval po trati (a opätovne sa registroval na kontrolách),
  • za úspešného pretekára bol vyhlásený aj ten, ktorý absolvoval všetky kontroly, no neskončil v cieli (napr. po štarte prišiel do cieľa a potom prešiel ostatné kontroly).