O kuharju, ki ni znal šteti
Testi
Testi: testi-o-kuharju-ki-ni-znal-steti.py
Naloga
V nekem filmi, katerega naslova se ne spomnim (smrdi pa mi po Johnu Cleesu) so imeli restavracijo, v kateri je znal šteti samo natakar. Če so gostje za mizo naročili, naročili pivo, tri sokove in dve kavi, je zatulil proti kuhinji "Pivo, sok, sok, sok, kava, kava".
Ogrevalna naloga
Napiši funkcijo, ki kot argument dobi seznam, kot je, recimo, ["pivo", (3, "sok"), (2, "kava")]
in izpiše
Torej, v seznamu s
so nizi in terke. Ko naletimo na niz, ga le izpišemo. Ko naletimo na terko, bo ta
vedno vsebovala število in niz. Niz moramo izpisati tolikokrat, kolikor pravi število.
Namig: če imamo nek objekt e
in bi radi preverili, ali gre za terko, to naredimo z
Obvezna naloga
Napiši funkciji expanded(s)
in expand(s)
. Funkcija expanded
naj prejme takšen
seznam, kot ga opisuje ogrevalna naloga, in kot rezultat vrne nov seznam, v katerem je vse, kar je potrebno pripraviti za to mizo.
Funkcija expand(s)
ne vrne ničesar, temveč spreminja podani seznam.
Dodatna naloga
Napiši funkciji imploded(s)
in implode(s)
, ki delata ravno nasprotno od expanded(s)
in expand(s)
.
Rešitev
Kot so pravilno ugotovili nekateri ... je bila ta domača naloga nekam lahka. ;)
Ogrevalna naloga
V ogrevalni nalogi ste, predvsem, preskusili isinstance
.
Expand(ed)
Skoraj enako kot izpis; naredimo nov seznam. Gremo prek podanega seznama in vanj dodajamo bodisi več elementov, bodisi enega.
Funkcija expand
je delala težave vsem, ki niso hoteli slediti
namigu in prebrati rešitve lanske domače naloge - ki je zahtevala praktično isto.
Kdor je bil pripravljen malo brati, je napisal le
Pomembno je, da spreminjamo s
, ne pa prirejamo imenu
s
. Tule smo vse elemente s-ja, s[:]
zamenjali z elementi
seznama, ki ga vrne expanded(s)
. Primer napačne rešitve bi bil
Takšna funkcija le prireja neki lokalni spremenljivki s
in ne
spreminja tistega, kar smo poslali funkciji kot argument.
Rešitev na daljši način v najboljšem primeru zahteva zanko while
.
Gremo čez seznam in kadar naletimo na terko, jo zamenjamo (tako da prirejamo s[i:i+1] - rezini, ki vsebuje to terko) seznam z ustreznim število ponovitev naročene reči. Z nizi ne storimo ničesar.
Zanka teče prek seznama, ki se medtem spreminja, a to nas ne moti. Tekla bo, dokler i
ne pride do konca seznama. Ob tem seveda naleti tudi na nize, ki smo jih na novo dodali, a nič hudega.
Nize tako ali tako pustimo pri miru.
Funkcijo je mogoče nekoliko pospešiti tako, da preskočimo naknadno dodane nize.
Implode(d)
Potrebovali bomo indekse, zato moramo prek seznama s for i in range(len(s))
ali for i, e in enumerate(s)
. Kaj izberemo, je stvar okusa. Meni je bolj
všeč drugo, tako da imamo v e
"trenutni" element seznama.
Znotraj zanke bo if
: če smo prišli do konca ponovitev določenega elementa,
zapišemo, kolikokrat se je ponovil (ali, če se je le enkrat, zapišemo le niz). Konec ponovitev
nastopi takrat, ko naslednji element ni enak temu (e != s[i+1]
) ali pa, ko
smo pravzaprav že pri zadnjem elementu (i == len(s) - 1
). Pri tem moramo najprej
preveriti ali gre za zadnji element, da pri e != s[i+1]
ne bi prišlo do
prekoračitve indeksa.
Spremenljivka c
šteje, kolikokrat se je določen element ponovil. Vsakič, ko
se ponavljanje prekine, ga postavimo nazaj na 1, sicer pa ga povečujemo.
Imploded se da napisati na več načinov. Še en, precej drugačen, je tale: pri vsakem elementu (zunanja zanka) pogledamo, koliko enakih elementov mu sledi (notranja zanka).
V dokaz, da se da tudi to: rešitev v eni vrstici: