Česa ni

V nalogi ste morali pokazati, da znate šteti pojavitve (ali pa odštevati, kot počnem v spodnji rešitvi) in da znate brisati iz srede seznama (in da razumete, zakaj je remove tule zelo slaba ideja). Mimogrede morate razumeti tudi, zakaj ne morete sestavljati novega seznama, oziroma, če ga, kako po tem vseeno spremeniti obstoječega. Večino tega ste pravzaprav srečali v drugi domači nalogi Največ n-krat, novo je le to, da je zaloga različnih stvari različna.

Za moj okus najpreprostejša rešitev je

def cesa_ni(narocila, zaloga):
    zaloga = zaloga.copy()
    i = 0
    while i < len(narocila):
        if zaloga.get(narocila[i]):
            zaloga[narocila[i]] -= 1
            i += 1
        else:
            del narocila[i]

V začetku naredim kopijo slovarja zaloga, ker ga bom spreminjal - odšteval bom "porabljene" stvari. Čez seznam grem z while, ne for. Zakaj, je razloženo v rešitvi domače naloge Največ n-krat. Koliko je zaloge, ne preverjam z zaloga[narocila[i]], saj to ne bi delalo, kadar stvari sploh ni na zalogi in v slovarju. Namesto tega uporabim zaloga.get(narocila[i]), ki takrat, ko nečesa ni v slovarju, vrne None. Pogoj v if zaloga.get(narocila[i]) bo torej neizpolnjen, če stvari ni v slovarju ali pa če je zaloga enaka 0; obe vrednosti, None in 0 sta namreč neresnični.

Če je stvar na zalogi, zmanjšamo zalogo in gledamo naslednjo stvar. Če je ni na zalogi, jo pobrišemo, vendar z del narocila[i] in ne remove, saj bi remove pobrisal prvo pojavitev in ne tiste, ki jo hočemo pobrisati.

Kdo je naročil kaj

Ta naloga je preverjala osnovno razumevanje slovarjev - kaj je ključ, kaj vrednost...

Gremo čez slovar in zlagamo v drugega. Ta drugi ima kot vrednosti množice in da se bodo pojavljale kar same od sebe, uporabimo defaultdict.

from collections import defaultdict

def kdo_kaj(narocila):
    r = defaultdict(set)
    for kdo, kaj in narocila.items():
        r[kaj].add(kdo)
    return r

Neizbrano

Tule me je zanimalo, kako se boste znašli z množicami in, če se ne boste odločili za množice, ali ste dovolj spretni, da naštrikate ustrezne zanke in pogoje.

Naredimo lahko tako:

def neizbrano(jedi, narocila):
    izbrano = set(narocila.values())
    ne = []
    for jed in jedi:
        if jed not in izbrano:
            ne.add(jed)
    return ne

Ali pa, preprosteje,

def neizbrano(jedi, narocila):
    return [jed for jed in jedi if jed not in set(narocila.values())]

Preštej naročila

Tole je seveda naloga iz rekurzije. Naredimo lahko tako:

def prestej_narocila(narocila, jed):
    if not narocila:
        return 0
    vseh = prestej_narocila(narocila[1:], jed)
    if narocila[0] == jed:
        vseh += 1
    return vseh

Ali, krajše (in z malo gršimi Pythonovskimi triki), tako:

def prestej_narocila(narocila, jed):
    return len(narocila) and (jed == narocila[0]) + prestej_narocila(narocila[1:], jed)

Natakar

To pa je seveda naloga iz objektnega programiranja. Zamisliti ste si morali smiselne atribute, znati spisati ustrezne metode ...

class Natakar:
    def __init__(self):
        self.osebe = defaultdict(set)

    def naroci(self, oseba, jed):
        self.osebe[oseba].add(jed)

    def prinesi(self, oseba, jed):
        self.osebe[oseba].remove(jed)
        if not self.osebe[oseba]:
            del self.osebe[oseba]

    def cakajoce_osebe(self):
        return set(self.osebe)

    def narocila(self):
        return self.osebe

    def kdo_je_narocil(self, jed):
        return {oseba for oseba, narocila in self.osebe.items() if jed in narocila}
Zadnja sprememba: sreda, 12. september 2018, 14.57