Rešitve s komentarji
Rešitve v enem kosu
Da si ustvarimo vtis o tem, koliko programiranja so zahtevale izpitne naloge, je tule rešitev celotnega izpita v obliki, kakršno smo pričakovali. Komentarji in nekoliko drugačne različice rešitev sledijo spodaj.
Komentarji rešitev
Sosedi
Gornja rešitev je najbolj preprosta. Naredimo nov seznam gremo od začetka do (skoraj) konca seznama in v vsakem koraku v novi seznam dodamo vsoto prejšnjega in naslednjega elementa.
Popaziti je potrebno le na robove. Ko je i
enak 0, s tem ni težav,
saj z s[-1]
dobimo ravno zadnji element. Ko bi bil i
na koncu seznama, pa bi z s[i + 1]
dobili napako.
In tega nočemo. ;) Zato smo pustili i
le do
len(s) - 1
in zadnji element dodali šele na koncu.
Druga rešitev je uporaba modula, s katerim se i + 1
, ko je
enak dolžini seznama, spremeni v 0.
Manj potrpežljivi rešijo nalogo takole:
ali takole
Trki
Naloga preverja, ali znamo uporabiti slovar. Vsako skrito besedo, ki jo naračunamo, vtaknemo v slovar - skrita beseda je ključ, vrednost pa beseda, iz katere jo dobimo. Vsakič, ko pridelamo novo skrito besedo, preverimo, ali smo jo že videli (ključi) in vrnemo besedo, iz katere je nastala (vrednost, ki pripada temu ključu).
Slaba rešitev je takšna:
Za 10000 besed mora bo ta funkcija 200000000-krat poklicala funkcijo skrij
.
Tudi če jo izboljšamo tako, da drugo besedo išče le med besedami, ki so na
seznamu pred prvo, tako da bo vsak par pogledala le enkrat,
nismo pridobili veliko, saj je program le dvakrat hitrejši - namesto
dvesto milijonkrat bo funkcij skrij
klical sto milijonkrat
(točneje, 99990000-krat). Program, ki uporabi slovar, jo kliče desettisočkrat.
Seveda pa zato porabi več pomnilnika.
Program, ki bi znal iskati tovrstne trke - pri določenih vrstah funkcije
skrij
, bi zelo zanimal NSA - pa še marsikoga drugega. Morda pa ga
že imajo?
Poštar iz Hamiltona
Najprej preverjanje zaporedja. I-ti element mora imeti vsaj eno skupno
števko z elementom i + 1. Ali je tako, preverimo tako, da element spremenimo
v niz (to je, niz števk), tega pa v množico. Izračunati je potrebno presek teh
dveh množic, set(str(s[i])) & set(str(s[i + 1]))
. Če je prazen,
ni skupne števke. Reč preverimo za vse i do predzadnjega (ki ga primerjamo z
zadnjim).
Malenkost bolj Pythonovska rešitev uporabi zip
.
Zdaj le preskusimo vse možne permutacije in vrnemo True
čim
naletimo na kakšno pravilno.
Poštar je iz Hamiltona, ker išče Hamiltonovo pot po grafu, katerega točke so hiše, dve hiši pa sta povezani, če imata skupno števko. Problem je NP-poln, kar, kot boste izvedeli v drugem letniku, za njegovo reševanje nimamo (bistveno) boljši postopkov kot je ta, ki ste ga ubrali v domači nalogi.
Največ sester
Najprej funkcija, ki pove, koliko sester ima najbolj osestreni potomec podane osebe. Prešteti moramo, koliko hčera ima oseba. Če ima toliko hčera, kolikor ima otrok, ima vsaka od njih toliko sester, kolikor je otrok - 1, saj ni sestra sama sebi. Če pa je med otroki tudi kak sin, ima toliko sester, kolikor je žensk. Z drugimi besedami,
Odtod gre po znanem vzorcu: najprej pogledamo, koliko sester ima najbolj osestreni otrok podane osebe, nato povprašamo otroke po najbolj osestrenih ljudeh iz njihovih rodbin in vrnemo maksimum vsega skupaj.
Ali, krajše
Tule pa je še druga, elegantna rešitev, ki uporablja eno samo funkcijo.
Blagajna
O blagajni pa ni kaj prida povedati. Potrebovala bo slovar, v katerem
shranjuje, kakšne bankovce ima. Najbolj prikladen je defaultdict
,
seveda pa bi šlo tudi z običajnim slovarjem. Vse, kar ostane (če znamo pisati
metode, seveda), je preprosto delo s slovarji.