Rešitve in razlaga
Izpit je bil sestavljen takole:
- Vstavi teže: telovadba z zankami, indeksiranje, pogoji
- Trgovanje: zanke in množice; vzorec "vsi" in "kdorkoli"
- Izmenjavanje: rekurzija
- Figura: seznami seznamov, indeksiranje in splošna programerska spretnost
- Blok: objektno programiranje
Vstavi teže
Tole je predvsem naloga iz spretnega dela z indeksi: eden se pomika naprej po seznamu imen, drugi pa se premakne na naslednjo težo le, ko se mora: vsakič, ko v prvem seznamu naletimo na žensko ime, vzamemo element iz drugega seznama.
Še kar dobra ideja bi bila, da se znebimo drugega števca tako, da teže
pobiramo iz seznama tež - vzamemo in pobrišemo, z metodo pop
.
Če naredite tako, testi javijo napako:
Seznama tež ne smemo spreminjati. Pač pa lahko naredimo kopijo in spreminjamo le-to.
Tako pridemo do naslednje zanimive rešitve z izpeljanimi seznami.
Trgovanje
Ali obstaja kdo, ki menja to za ono, lahko preverimo tako, da se zapeljemo
čez ponudbe in takrat, ko najdemo takšno, ki ustreza, vrnemo True
.
Če ni nobene, vrnemo False
.
Menjave gredo ravno obratno: čim najdem takšno, ki ni možna, vrnem
False
. Če takšne ni, vrnem True
.
Tu gre za dva vzorca, ki ju gledamo že od prvih tednov programiranja, odkar
smo, recimo, iskali praštevila. Ko smo se učili o izpeljanih seznamih in
generatorjih, smo izvedeli, da ta vzorec nadomestimo z generatorjem, ki ga
damo funkciji any
ali all
. Če torej znamo
uporabljati generatorje, se funkciji poenostavita v
Izmenjavanje
Tole bi moral biti deja vu: nekoč smo preverjali, ali seznam izmenično vsebuje soda in liha števila.
Če ima seznam manj kot dva elementa, je v redu. Sicer morata biti prva dva elementa različna (to, ali se prvi konča z a mora biti različno od tega, ali se drugi), izmenjujoč pa mora biti tudi ostanek.
Preprostejši, a manj eleganten način je napisati tri funkcije. Ena pravi,
da se na seznamu izmenjujejo moški in ženske (začenši z moškim), če je seznam
praze, ali pa je prvi moški, v ostanku pa se izmenjujejo ženske in moški. Druga
funkcija pravi obratno, le z zamenjanima spoloma. Funkciji torej kličeta ena
drugo, zato je to rekurzija. Tretja funkcija pa vrne True
, če se
v seznamu izmenjujejo bodisi moški in ženske bodisi ženske in moški.
Figura
Tole zahteva nekaj spretnosti. Funkcijo spremeni_smer
lahko
napišemo z goro if
ov, s slovarji... ali pa s preprostim nizom.
Ker je manj elegantnih rešitev kolikor hočemo, bomo pokazali le slednjo,
elegantno.
V nizu je seznam smeri v smeri urinega kazalca. Ko se vrtimo v desno, gremo
po tem seznamu naprej (gor, desno, dol, levo); ko se vrtimo levo, gremo po
njem nazaj (levo, dol, desno, gor). Pogledamo indeks trenutnega znaka
smeri.index(smer)
, k njem prištejemo 0, -1 ali 1, odvisno od tega,
kam se vrtimo ({"F": 0, "L": -1, "R": 1}[obrat]
). Potem iz niza
vzamemo ustrezno črko - tisto, z novim indeksom.
Popaziti je potrebno le na robove. Če sem na 0 in grem levo, pridem na -1, kar je zadnji znak in vse je lepo. Če sem na zadnjem znaku (3) in grem desno, pa pridem na 4; moral bi na 0. To lahko rešim tako, da po prištevanju izračunamo ostanek po deljenju s 4, kar mi spremeni 4 v 0.
Taka rešitev zahteva nekaj zaloge programerskih trikov. Na srečo pa naloga tudi za tiste, ki jih nimajo, ni tako težka, le malenkost daljši program bodo napisali.
Drugo funkcijo, smo letos pisali ničkolikokrat - z želvami, s potniki...
Včasih smo uporabljali if
e, včasih slovarje, morda smo omenili
rešitev s kompleksnimi števili. Tokrat naredimo nekaj sorazmerno izvirnega.
Potovanje je zdaj preprosto: z zanko while
preganjamo figuro
okrog, dokler ne pade čez rob plošče ali pa se polje ponovi. Obiskana polja
bomo hranili v seznamu, ki ga moramo vrniti. Manjše težave nam povzroča le to,
da je v seznamu tudi zadnje obiskano polje. Tega se rešimo tako, da namesto
(x, y) not in pot
preverjamo (x, y) not in pot[:-1]
.
Potovanje se torej konča, ko trenutno polje najdemo v seznamu vseh polj, razen
zadnjega dodanega (ki je seveda trenutno).
Kdor se ni spomnil tega trika, lahko uporabi tudi enega, ki smo ga spoznali
na predavanjih: ali pot vsebuje same unikatne elemente, preverimo tako, da
spremenimo seznam v množico in pogledamo, ali sta enako dolga,
len(pot) == len(set(pot))
.
Knjižnica
Odločiti se moramo, kako bomo shranjevali knjige. Zaradi metode
vrni
je najbolj priročen slovar, saj nam tako ne bo potrebno
po seznamu iskati knjige z danim naslovom.
Razred je potem preprost: konstruktor pripravi množico, izposodi
doda knjigo v slovar, vrni
jo pobriše, izposojeno
vrne množico ključev. Za računanje zamudnine gremo prek vrednosti v slovarju
in za vsako zamujeno knjigo k zamudnini prištejemo število dni zamude.
Zadnjo metodo bi lahko napisali tudi s sum
in generatorjem,
vendar s tem ni bi nič posebnega pridobili.