Vse naloge

Za občutek so tu najprej rešitve vseh nalog. Različice rešitev in komentarji so spodaj.

def v7raus(s): return [e for e in s if e % 7 != 0] def sekajo(krogi): for i, (x1, y1, r1) in enumerate(krogi): for x2, y2, r2 in krogi[:i]: if (x1 - x2)**2 + (y1 - y2)**2 < (r1 + r2)**2: return True return False class Blagajna: def __init__(self, bankovci): self.bankovci = bankovci def izplacaj(self, bankovci): for bankovec, kolicina in bankovci.items(): if kolicina > self.bankovci.get(bankovec, 0): raise ValueError for bankovec, kolicina in bankovci.items(): self.bankovci[bankovec] -= kolicina def vsota(self): v = 0 for bankovec, komadov in self.bankovci.items(): v += bankovec * komadov return v def v_stavke(s): return [x+"." for x in "".join(s).split(".") if x] class listmod(list): def __getitem__(self, item): return super(listmod, self).__getitem__(item % len(self)) def __setitem__(self, item, value): return super(listmod, self).__setitem__(item % len(self), value)

Po nalogah

Naloga A

Funkcija, ki ste jo napisali za domačo nalogo, gre nekje prek seznama stolpcev, ki ste ga najbrž dali v nek niz "abcdefgh". Na izpitu ste morali dodati še dva stolpca, "abcdefghij".

Naloga B

Skopirate funkcijo add, jo preimenujete v mul in zamenjate seštevanje z množenjem.

Večkratniki 7 raus!

Tole je v bistvu (malo lažje kot) poštevanka števila 7. Praktično enaka naloga je rešena v zapiskih.

def v7raus(s): return [e for e in s if e % 7 != 0]

Daljši način je takšen:

def v7raus(s): t = [] for e in s: if e % 7 != 0: t.append(e) return t

Sekajoči se krogi

Naloga ni povsem tuja zadnji domači nalogi, kjer ste morali preveriti, ali je krog zadel katerega od eksplodiranih krogov. Edina komplikacija je v tem, da morate preveriti sekanje vsakega kroga z vsakim in se obenem izogniti temu, da bi se krog sekal sam s sabo. Kot je namigoval namig, nam pride prav, če poznamo indeks kroga, saj lahko tako preverjamo, ali se i-ti krog (krog[i]) seka s katerim od krogov pred njim (krogi[:i]).

def sekajo(krogi): for i, (x1, y1, r1) in enumerate(krogi): for x2, y2, r2 in krogi[:i]: if (x1 - x2)**2 + (y1 - y2)**2 < (r1 + r2)**2: return True return False

Ob popravljanju izpitov sem naletel na tole:

for a in krogi: for b in krogi: if a is not b:

Tako napisana funkcija sicer vzame dvakrat več časa kot gornja, poleg tega pa je izvirna koda brez potrebe majčkeno bolj zapletena, vendar: bravo! Na is not res nisem pomislil. Odličen primer njegove rabe.

Blagajna

Naloga preverja, ali znate sestaviti razred. V metodah ni nič posebnega, le malo opletanja s slovarji.

class Blagajna: def __init__(self, bankovci): self.bankovci = bankovci def izplacaj(self, bankovci): for bankovec, kolicina in bankovci.items(): if kolicina > self.bankovci.get(bankovec, 0): raise ValueError for bankovec, kolicina in bankovci.items(): self.bankovci[bankovec] -= kolicina def vsota(self): v = 0 for bankovec, komadov in self.bankovci.items(): v += bankovec * komadov return v

Povedi

Najprej rešimo poenostavljeno različico, ki upošteva samo piko. Dobljene sezname samo zlepimo skupaj, jih ločimo glede na piko in k vsakemu elementu dodamo piko, saj jo je split pobrisal.

def v_stavke(s): return [x+"." for x in "".join(s).split(".") if x]

Če hočemo upoštevati vsa tri ločila, moramo uporabiti regularne izraze. Napišemo, preprosto, regularni izraz, ki opisuje stavek: stavek je sestavljen iz nekih znakov, ki niso ločila (torej niso pika, vprašaj ali klicaj) in se poljubnokrat ponovijo, [^.?!]*. Slediti jim mora ločilo, [.?!]. In to je vsa umetnost: v skupaj zlepljenih nizih iz seznama, ki smo ga dobili kot argument ("".join(s)) moramo poiskati vse (findall pojavitve vzorca [^.?!]*[.?!].

import re def v_stavke(s): return re.findall("[^.?!]*[.?!]", "".join(s))

Ko sem na predavanjih povedal, da je regularne izraze dobro znati, ker so nekatere naloge na izpitu brez njih precej bolj zoprne, sem govoril po pravici. Rešitev brez regularnih izrazov je takšna:

def v_stavke(s): s = ["".join(s)] for locilo in ".?!": ns = [] for e in s: pp = e.split(locilo) for p in pp[:-1]: ns.append(p+locilo) if pp[-1]: ns.append(pp[-1]) s = ns return s

Seznam po modulu

Ta naloga je variacija domače naloge Neobčutljivi slovar, le da je potrebno hekati seznam. Kdor si je pogledal komentarje rešitev domačih nalog, je ravnal pametno, saj je lahko uporabil tole preprosto rešitev:

class listmod(list): def __getitem__(self, item): return super(listmod, self).__getitem__(item % len(self)) def __setitem__(self, item, value): return super(listmod, self).__setitem__(item % len(self), value)
Zadnja sprememba: petek, 27. januar 2012, 11.20