Ogrevalna naloga

Napiši funkcijo n_dolgih_imen(oseba), ki prejme ime neke osebe in vrne število oseb v rodbini te osebe, katerih imena imajo več kot pet črk.

Napiši funkcijo vsa_dolga_imena(oseba), ki prejme ime neke osebe in vrne množico imen vseh oseb v rodbini te osebe, katerih imena imajo več kot pet črk.

Klic vsa_dolga_imena("Elizabeta") torej vrne {'Aleksander', 'Alenka', 'Barbara', 'Elizabeta', 'Herman', 'Ludvik', 'Margareta'}.

Obvezna naloga

Funkcije, ki jih boš napisal(a) v tej nalogi, ne smejo klicati funkcij iz ogrevalne naloge! Pa tudi nobenih drugih funkcij (razen vdelanih, kot so sqrt, sum, len, randint in podobne), temveč le same sebe!!!

Potomci neke osebe so njeni sinovi in hčere, vnukinje in vnuki in tako naprej. Se pravi cela rodbina, razen te osebe same.

Napiši funkcijo n_dolgih_imen_pot(oseba), ki prejme ime neke osebe in vrne število potomcev osebe, katerih imena imajo več kot pet črk.

Napiši funkcijo vsa_dolga_imena_pot(oseba), ki prejme ime neke osebe in vrne množico potomcev te osebe, katerih imena imajo več kot pet črk.

Klic vsa_dolga_imena_pot("Elizabeta") torej vrne {'Aleksander', 'Alenka', 'Barbara', 'Herman', 'Ludvik', 'Margareta'}. Isto kot prej, le brez Elizabete.

Rešitev

Prvi dve sta bili (bi morali biti) preprosti, saj sta praktično enaki temu, kar smo delali na predavanjih, le da tu ne štejemo vseh oseb, temveč le tiste z dolgimi imeni. En dodatni if, torej.

def n_dolgih_imen(oseba):
    dolgih = 0
    if len(oseba) > 5:
        dolgih += 1
    for otrok in otroci[oseba]:
        dolgih += n_dolgih_imen(otrok)
    return dolgih

def vsa_dolga_imena(oseba):
    dolga = {oseba} if len(oseba) > 5 else set()
    for otrok in otroci[oseba]:
        dolga |= vsa_dolga_imena(otrok)
    return dolga

Pri drugih dveh se zafrkavamo z osebo, katere rodbino opazujemo. Če je ne dodamo (recimo tako, da namesto dolga = {oseba} if len(oseba) > 5 else set() pišemo le dolga = set()), potem ne bomo dodali nikogar.

Problem najpreprosteje rešimo tako, da namesto osebe dodajamo njene otroke.

def n_dolgih_imen_pot(oseba):
    dolgih = 0
    for otrok in otroci[oseba]:
        if len(otrok) > 5:
            dolgih += 1
        dolgih += n_dolgih_imen_pot(otrok)
    return dolgih

def vsa_dolga_imena_pot(oseba):
    dolga = {otrok for otrok in otroci[oseba] if len(otrok) > 5}
    for otrok in otroci[oseba]:
        dolga |= vsa_dolga_imena_pot(otrok)
    return dolga

Vse funkcije se dajo brez težav napisati tudi v eni vrstici; "pravi prorgamerji" bi jih v praksi najbrž napisali tako. One s preštevanjem bi morali znati tudi mi (če se spomnimo, da je True isto kot 1 in False isto kot 0), one z množicami pa zahtevajo, da uporabimo reduce ali chain - pri vsa_dolga_imena lahko vidite obe možnosti. Tega vam seveda ni treba znati ... če ste radovedni, pa se le razglejte.


def n_dolgih_imen(oseba): return (len(oseba) > 5) + sum(n_dolgih_imen(otrok) for otrok in otroci[oseba]) def vsa_dolga_imena(oseba): return set(chain(*(vsa_dolga_imena(otrok) for otrok in otroci[oseba]))) \ | ({oseba} if len(oseba) > 5 else set()) def vsa_dolga_imena(oseba): return reduce( set.union, (vsa_dolga_imena(otrok) for otrok in otroci[oseba]), {oseba} if len(oseba) > 5 else set()) def n_dolgih_imen_pot(oseba): return sum((len(otrok) > 5) \ + n_dolgih_imen_pot(otrok) for otrok in otroci[oseba]) def vsa_dolga_imena_pot(oseba): return reduce( set.union, (({otrok} if len(otrok) > 5 else set()) | vsa_dolga_imena(otrok) for otrok in otroci[oseba]), set())

Dodatna naloga

Ta najbrž ni nič težja od ostalih. Morda celo lažja. :)

Napiši funkcijo vecji_od_starsev(oseba), ki vrne število vseh potomcev te osebe, katerih imena so daljša od imen njihovih staršev.

Rešitev

def vecji_od_starsev(oseba):
    return sum((len(otrok) > len(oseba)) + vecji_od_starsev(otrok) for otrok in otroci[oseba])

Dodaten izziv

Napiši funkcijo izpisi(oseba), ki izpiše rodbino osebe tako, da izpiše najprej to osebo, nato njene otroke, potem vnuke, potem pravnuke in tako naprej, po nivojih.

Funkcija morda ne bo rekurzivna. Lahko pa je. Nerekurzivna je v resnici preprostjša.

Testov za dodatni izziv ni.

Rešitev

def izpisi(oseba):
    izpisati = [oseba]
    for ime in izpisati:
        print(ime)
        izpisati += otroci[ime]

A nisem rekel, da je lažje brez rekurzije?

Testi

Last modified: Tuesday, 31 March 2020, 9:17 AM