Naloga se nanaša na nalogi prejšnjih dveh tednov (Šikaniranje, Lokacije ovir): večinoma je potrebno le preoblikovati to, kar ste programirali takrat, v funkcije. Pri reševanju smete uporabiti tudi objavljene rešitve prejšnjih dveh nalog.
Napisati je potrebno naslednje funkcije:
stevilo_ovir(ovire)
prejme ovire v obliki seznama trojk
(x0, x1, y)
in vrne število ovir.dolzina_ovir(ovire)
vrne skupno dolžino vseh ovirsirina(ovire)
vrne širino kolesarke steze, se pravi
najbolj desno koordinato v seznamu ovirpretvori_vrstico(vrstica)
prejme vrstico v obliki niza,
sestavljenega iz znakov #
in .
ter vrne seznam
parov (x0, x1) (ogrevalni del domače naloge prejšnjega tedna)dodaj_vrstico(bloki, y)
prejme seznam, kakršnega vrača
prejšnja funkcija in neko število y
. Vrniti mora seznam, v
katerem je vsakemu paru dodan y
. Klic
dodaj_vrstico([(3, 4), (6, 8), (11, 11)], 3)
vrne
[(3, 4, 3), (6, 8, 3), (11, 11, 3)]
.pretvori_zemljevid(zemljevid)
dobi zemljevid v obliki
seznama nizov in vrne seznam ovir (obvezna domača naloga prejšnjega
tedna). Funkcija mora uporabiti prejšnji dve funkciji - testi bodo to
preverili tako, da bodo začasno zamenjali tvojo funkcijo z neko drugo,
ki vrača napačne številke in preverili, ali so številke res "pravilno
napačne".globina(ovire, x)
prejme seznam ovir (v obliki trojk)
in vrne vrstico, v kateri bi kolesar, ki se vozi po stolpcu
x
, naletel na oviro (naloga izpred dveh tednov).naj_stolpec(ovire)
vrne stolpec, v katerem kolesar
pride najdlje in vrstico, do katere pride. Možno je tudi, da v kakem
stolpcu ni ovire; v tem primeru vrne koordinato tega stolpca in
None
.senca(ovire)
vrne seznam, katerega elementa so
True
oz. False
glede na to, ali stolpec
vsebuje kako oviro ali ne. Če je širina poti 5 in sta drugi in zadnji
stolpec brez ovir, vrne
[True, False, True, True, False]
.def stevilo_ovir(ovire):
return len(ovire)
def dolzina_ovir(ovire):
= 0
dolzina for x0, x1, _ in ovire:
+= x1 - x0 + 1
dolzina return dolzina
def sirina(ovire):
= 0
najx for _, x1, _ in ovire:
if x1 > najx:
= x1
najx return najx
def pretvori_vrstico(vrstica):
= "." + vrstica + "."
vrstica = []
bloki for i, znak in enumerate(vrstica):
if znak == "#":
if vrstica[i - 1] == ".":
= i
zacetek if vrstica[i + 1] == ".":
bloki.append((zacetek, i))return bloki
def dodaj_vrstico(bloki, y):
= []
z_vrstico for x0, x1 in bloki:
z_vrstico.append((x0, x1, y))return z_vrstico
def pretvori_zemljevid(zemljevid):
= []
ovire for y, vrstica in enumerate(zemljevid, start=1):
+= dodaj_vrstico(pretvori_vrstico(vrstica), y)
ovire return ovire
def globina(ovire, x):
= None
najy for x0, x1, y in ovire:
if x0 <= x <= x1 and (najy == None or y < najy):
= y
najy return najy
def naj_stolpec(ovire):
= 0
naj_y for x in range(1, sirina(ovire) + 1):
= globina(ovire, x)
g if g == None:
return x, None
if g > naj_y:
= g
naj_y = x
naj_x return naj_x, naj_y
def senca(ovire):
= []
zaprti for x in range(1, sirina(ovire) + 1):
== None)
zaprti.append(globina(ovire, x) return zaprti
Komentar si zasluži le par funkcij.
pretvori_zemljevid
V pretvori_zemljevid
dodamo vrstico z +=
ne
z append
.
# Tole ne deluje!
for y, vrstica in enumerate(zemljevid, start=1):
ovire.append(dodaj_vrstico(pretvori_vrstico(vrstica), y))
Metoda append
bi dodala vrstico kot nov element seznama
- se pravi vrstico, ne njenih elementov. Tako bi dobili seznam
seznamov.
Alternative so extend
, ki naredi isto kot
+=
,
for y, vrstica in enumerate(zemljevid, start=1):
ovire.extend(dodaj_vrstico(pretvori_vrstico(vrstica), y))
ali pa dodajanje posamičnih elementov, kar pa je daljše, nepotrebno in počasnejše
for y, vrstica in enumerate(zemljevid, start=1):
for ovira in dodaj_vrstico(pretvori_vrstico(vrstica), y):
ovire.append(ovira)
V tej funkciji je zanimivo tudi, kako pridemo do številke vrstice.
Lahko štejemo sami, s spremenljivko, ki jo sami povečujemo, lahko pa
uporabimo enumerate
. Če funkciji enumerate
dodamo argument start=1
, bo štela od 1
. Sicer
pa pač šteje od 0
in kot številko vrstice uporabimo
y + 1
.
naj_stolpec
V tej funkciji je praktično, da takrat, ko najdemo prost stolpec, kar
takoj vrnemo x, None
. To prekine zanko, konča funkcijo,
vrne rezultat.
senca
Dve stvari. Ta funkcija lahko kliče funkcijo globina
.
Pravzaprav je zelo koristno, da jo, saj sicer ponovimo večino kode te
funkcije.
Druga:
== None) zaprti.append(globina(ovire, x)
in ne
if globina(ovire, x) == None:
True)
zaprti.append(else:
False) zaprti.append(
Seveda deluje tudi drugo, vendar ni smiselno, saj je
globina(ovire, x) == None
že vrednost, ki jo želimo dodati
v seznam. (Zanimivo: študenti rezultat primerjanja stalno dojemajo kot
pogoj, ki ga lahko uporabljajo v if
in
while
, ne pa kot vrednost, ki jo lahko uporabijo, kjerkoli.
Mogoče bi se to rešilo tako, da bi že eno predavanje, preden začnemo s
pogoji, predstavil logične izraze, kot nekaj, kar pač vrne
True
ali False
?!)