Trdnjava

Čeprav naloga po zgodbici spominja na Kojna, zahteva povsem druge "veščine": v bistvu preverja samo ali znamo napisati zanko in jo na primernem mestu prekiniti.

def trdnjava(premiki): p = (0, 0) for kam, koliko in premiki: if kam == "U": p = (p[0] - int(koliko), p[1]) elif kam == "D": p = (p[0] + int(koliko), p[1]) elif kam == "L": p = (p[0], p[1] - int(koliko)) elif kam == "R": p = (p[0], p[1] + int(koliko)) if p == (0, 0): return True return False

Pozicija, p je tule striktno terka. Namesto nje bi lahko uporabljal tudi x in y. Stvar okusa. Ne spreglejte pa, da se da tudi niz razpakirati - tule sem ga razpakiral v kam in koliko.

Takšne naloge se sicer da vedno učinkovito ukrotiti s kompleksnimi števili, takole (j v večini programskih jezikov pomeni imaginarno enoto, tisto, kar matematiki pogosteje zapisujejo kot i):

def trdnjava(premiki): smeri = {"U": -1j, "D": 1j, "L": -1, "R": 1} p = 0 for kam, koliko in premiki: p += int(koliko) * smeri[kam] if p == 0: return True return False

Natakar

Naloga, ki bi bila zelo preprosta, če bi sledili namigu - ali pa se sami spomnili - na defaultdict. Naredimo takšen slovar, nato pa se sprehodimo z zanko čez naročila in dodajamo ali preklicujemo jedi.

import collections def narocila(s): po_strankah = collections.defaultdict(list) for oseba, jed in s: if jed[0] == "-": if jed[1:] in po_strankah[oseba]: po_strankah[oseba].remove(jed[1:]) else: po_strankah[oseba].append(jed) return dict(po_strankah)

Primerjanje seznamov

Te naloge smo se bali, vendar se je izkazala za najpopularnejšo. Večinoma ste jo reševali tako, da ste prešteli, kolikokrat je element prvega seznama večji od drugega in kolikokrat je obratno. Potem ste to primerjali z dolžino seznamov: če je prvi vedno večji, vrnete 1, če vedno manjši, -1, sicer pa 0.

To torej znate. Tule pa je nekoliko drugačna rešitev. Kot sem obljubil, snov zadnjega predavanja ni obvezna, je pa priročna:

def primerjaj(s, t): if len(s) != len(t): return 0 if all(si < ti for si, ti in zip(s, t)): return -1 if all(si > ti for si, ti in zip(s, t)): return 1 return 0

Kolikor vem, pa sem vam povedal dovolj, da bi jo morali znati rešiti tudi takole (predlagam, da se premozgate skozi to rešitev, saj ima lep trik):

def primerjaj(s, t): v = [max(*x) for x in zip(s, t)] return (s == v) - (t == v)

Catch je v tem, da je v seznam, sestavljen iz večjih (istoležnih elementov). Spomnimo se še, da je True isto kot 1. Če je seznam večjih elementov enak s, imamo return 1 - 0, če je enak t, imamo return 0 - 1, sicer return 0 - 0. Edini bug je, da bo funkcija za seznama [1, 2], [0, 2] vrnila 1, čeprav bi morala 0, ker niso vsi elementi prvega strogo večji od elementov drugega. Nič ni popolno.

Editor

Bodite pozorni na drugi if; tu so se na izpitu dogajale težke (in včasih tudi napačne) akrobacije. V drugi funkciji sem uporabil zip. Brez njega bi bilo potrebno uporabljati indekse.

def crka(c, a): if a == "U": return c.upper() if "0" <= a <= "9": return c * int(a) if a == "x": return "" if a == ".": return c def kodiraj(beseda, koda): r = "" for c, a in zip(beseda, koda): r += crka(c, a) return r

Drugo funkcijo je seveda mogoče napisati tudi nekoliko krajše:

def kodiraj(beseda, koda): return "".join(crka(c, a) for c, a in zip(beseda, koda))

Največje število

Pa še vaja iz razredov in rekurzije. Mislim, da imate srečo, da je bilo oboje v isti nalogi; če bi bilo v dveh različnih, bi bili rezultati opazno slabši...

class StevilkaPlus(Stevilka): def najvecji(self): naj = self.vrednost() n = self.levi() if n: naj = max(naj, n.najvecji()) n = self.desni() if n: naj = max(naj, n.najvecji()) return naj

Gre pa tudi krajše.

class StevilkaPlus(Stevilka): def najvecji(self): l, d = self.levi(), self.desni() return max(self.vrednost(), l.najvecji() if l else -1, d.najvecji() if d else -1)
Zadnja sprememba: torek, 5. februar 2013, 22.53