Sestavite funkcijo vsota_potenc(k, n)
, ki vrne vsoto
>>> vsota_potenc(10, 2)
1025
Ali znaš napisati rešitev, kjer funkcija vsebuje en sam stavek oblike return nekIzraz
def vsota_potenc(k, n): '''Vrne vsoto potenc''' vsota = 0 for i in range(1, n+1): # preko vseh členov člen = i**k # trenutni člen vsota += člen return vsota def vsota_potencV2(k, n): '''Vrne vsoto potenc s pomočjo izpeljanih seznamov''' return sum([i**k for i in range(1, n+1)])
Sestavite funkcijo inverzna_harmonicna(x)
, ki pove, koliko členov
harmonične vrste
>>> inverzna_harmonicna(2)
4
Ali bi pri tej nalogi šlo z izpeljanim seznamom?
def inverzna_harmonicna(x): '''Koliko členov harmonične vrste moramo sešteti, da presežemo x''' trenutnaVsota = 0 k = 1 # števec členov (enak imenovalcu) while trenutnaVsota <= x: # nismo še preko vsote trenutnaVsota += 1 / k k += 1 return k - 1 # ker smo začeli šteti z 1 pred zanko
Sestavite funkcijo vsota_stevk(n)
, ki vrne vsoto števk danega pozitivnega celega števila.
Zgled:
>>> vsota_stevk(2014)
7
Če celo število ni pozitivno, vrnemo 0. Ali znaš nalogo rešiti z izpeljanim seznamom, s pomočjo enega samega stavka return?
def vsota_stevk(n): '''Vrne vsoto števk pozitivnega celega števila''' return sum([int(stevka) for stevka in str(n)]) if n > 0 else 0
Sestavite funkcijo vsote(n)
, ki izračuna, na koliko načinov lahko
zapišemo naravno število n
kot vsoto naraščajočega zaporedja naravnih
števil. Na primer, klic vsote(7)
vrne 5
, ker lahko 7 zapišemo na
naslednje načine:
7 = 7
7 = 1 + 6
7 = 2 + 5
7 = 3 + 4
7 = 1 + 2 + 4
Opomba: Ta naloge je malce težja od ostalih iz tega sklopa.
def stej(m, j): """ Pomožna funkcija, ki šteje vsote števila m, pri čemer mora biti prvi člen v vsoti večji ali enak številu j. """ if m == 0: return 1 elif j > m: return 0 else: return sum([stej(m-i, i+1) for i in range(j, m+1)]) def vsote(n): return stej(n, 1)
V seznamu imamo podatke o prilivih in odlivih s tekočega računa. Pozitivna števila predstavljajo priliv (polog denarja), negativna pa dvig. Vsak element seznama predstavlja en dan. Če na nek dan ni prilivov ali dvigov, je vrednost v seznamu 0. Privzemite, da je na začetku stanje na računu 0.
Sestavite funkcijo koncno_stanje(spremembe)
, ki iz danega seznama
prilivov in odlivov izračuna končno stanje.
Pri rešitvi ne uporabi zanke neposredno v kodi te funkcije.
def koncno_stanje(spremembe): '''Izračuna končno stanje na računu''' return sum(spremembe)
Sestavite funkcijo stanja(spremembe)
, ki iz danega seznama
prilivov in odlivov ustvari seznam vmesnih stanj na računu.
Privzemite, da je na začetku stanje na računu 0. To naj bo prva "sprememba" v seznamu
>>>stanja([10, -5, 20, -6])
[0, 10, 5, 25, 19]
Ali znaš nalogo rešiti tako, da vsebuje le stavek oblike return <nekIzraz>
?
def stanja(spremembe): '''Vrne seznam vmesnih stanj na računu''' trenutnoStanje = 0 stanja = [0] for sprememba in spremembe: # pregledamo vse transkacije v seznamu trenutnoStanje += sprememba stanja.append(trenutnoStanje) return stanja def stanjaV2(spremembe): '''Vrne seznam vmesnih stanj na računu''' # nalogo lahko rešimo s pomočjo izpeljanih seznamov # na vsakem seznamu generiramo ustrezni začetni del seznama in ga seštejemo return [sum(spremembe[:i]) for i in range(len(spremembe)+1)]
Sestavite funkcijo ekstrema(spremembe)
, ki pri danih spremembah
stanja poišče vrednosti, ko je bilo stanje na računu najnižje oziroma
najvišje. Pri tem seveda zanemari začetno stanje 0 in prepostavi, da je prišlo do
vsaj ene spremembe
Stanji naj vrne v obliki nabora.
>>>ekstrema([10, -5, 20, -6])
(5, 25)
Rešitev poišči brez uporabe zank neposredno v kodi te funkcije.
def ekstrema(spremembe): '''Vrne najnižje in najvišje stanje''' s = stanja(spremembe)[1:] # uporabimo funkcijo prejšnje naloge, a začetno stanje (0) zavržemo najnizje = min(s) najvisje = max(s) return (najnizje, najvisje)
Sestavite funkcijo kdaj_ekstrema(spremembe)
, ki pri danih spremembah
stanja poišče število dni od začetka, ko je bilo stanje na računu najnižje oziroma
najvišje. Rezultat naj vrne v obliki nabora.
>>>kdaj_ekstrema([10, -5, 20, -6])
(2, 3)
Rešitev poišči brez uporabe zank neposredno v kodi te funkcije.
def kdaj_ekstrema(spremembe): '''Vrne število dni od začetka, ko smo dosegli najnižje in najvišje stanje''' s = stanja(spremembe) [1:] # uporabimo funkcijo prejšnje naloge, a začetno stanje (0) zavržemo najnizje = s.index(min(s)) + 1 najvisje = s.index(max(s)) + 1 return (najnizje, najvisje)
Sestavite funkcijo razlika(spremembe, i, j)
, ki poišče razliko
stanj med dnevoma z indeksom i
in j
. Na dan 0 je bilo seveda stanje 0.
>>>razlika([10, -5, 20, -6], 1, 3)
15
>>>razlika([10, -5, 20, -6], 1, 2)
-5
Predpostavite lahko, da je i
manjši ali enak j
.
Rešitev poišči brez uporabe zank neposredno v kodi te funkcije.
def razlika(spremembe,i,j): '''Vrne spremembo med dnevoma i in j''' return sum(spremembe[i:j])
Sestavite funkcijo najvecja_razlika(spremembe)
, ki poišče največji
relativni priliv. Z drugimi besedami, poišče največjo vrednost, ki jo
zavzame vsota poljubnega strnjenega podseznama.
Tako na primer najvecja_razlika([10, -13, 3, 20, -2, 5])
vrne
3 + 20 - 2 + 5 = 26.
Če je seznam spremembe
prazen, naj funkcija vrne None
.
def najvecja_razlika(spremembe): '''Izračuna največji relativni priliv v nekem obdobju''' if spremembe == []: return None # ni bilo nobenih sprememb n = len(spremembe) najRaz = spremembe[0] # načeloma je kandidat kar dogajanje prvi dan for začetek in range(0, n): for konec in range(začetek, n): # vsi možni začeteki in konci podseznamov vsotaPodsez = 0 for indeks in range(začetek, konec+1): # izračunamo vsoto podseznama vsotaPodsez += spremembe[indeks] if vsotaPodsez > najRaz: # našli smo večji priliv najRaz = vsotaPodsez return najRaz
Sestavite funkcijo najvecja_razlikaV2(spremembe)
, ki poišče največji
relativni priliv. Z drugimi besedami, poišče največjo vrednost, ki jo
zavzame vsota poljubnega strnjenega podseznama.
Tako na primer najvecja_razlikaV2([10, -13, 3, 20, -2, 5])
vrne
3 + 20 - 2 + 5 = 26.
Če je seznam spremembe
prazen, naj funkcija vrne None
.
Uporabi izpeljanje sezname!
def najvecja_razlikaV2(spremembe): '''Izračuna največji relativni priliv v nekem obdobju''' if spremembe == []: return None # ni bilo nobenih sprememb n = len(spremembe) return max(sum(spremembe[i:j+1]) for i in range(0, n) for j in range(i, n)) # generiramo vse možne podsezname, jih seštejemo # in med vsotami poiščemo največjo
Pravimo, da je sprehod po točkah v ravnini cik-cakast, če gremo iz
točke
Sestavite funkcijo je_cikcakast(sprehod)
, ki vrne True
natanko tedaj,
kadar je sprehod, podan z zaporedjem točk sprehod
, cik-cakast. Zgled:
>>> je_cikcakast([(1, 1), (2, 0), (3, -1), (4, 0), (5, 1)])
True
def je_cikcakast(sprehod): '''Ali je sprehod, podan kot seznam parov koordinat, cik cakast''' for i in range(len(sprehod) - 1): # jemali bomo po dve točki - začetek in konec, zato končamo pri predzadnji točki (x1, y1), (x2, y2) = sprehod[i], sprehod[i + 1] # razpakiranje podatkov if x2 != x1 + 1 or abs(y2 - y1) != 1: return False # že en ne cikcakast premik pove rezultat return True # vsi premiki so bili cikcak
Sestavite funkcijo prestavi_v_1kvadrant(sprehod)
, ki sprehod zamakne
tako, da v celoti poteka izključno v 1. kvadrantu ter da je njegova prva
točka na ordinatni, njegova najnižja točka pa na abscisni osi. Zgled:
>>> prestavi_v_1kvadrant([(1, 1), (2, 0), (3, -1), (4, 0), (5, 1)])
[(0, 2), (1, 1), (2, 0), (3, 1), (4, 2)]
def prestavi_v_1kvadrant(sprehod): '''Prestavi sprehod, podan kot seznam parov koordinat, v 1kvadrant''' # poiščemo minimalno x in min. y koordinato min_x, min_y = sprehod[0] for tockaX, tockaY in sprehod: min_x = min(min_x, tockaX) # manjši od obeh je kandidat za min min_y = min(min_y, tockaY) novSprehod = [] for x, y in sprehod: #premaknemo za ustrezna minimuma novSprehod += [(x - min_x, y - min_y)] return novSprehod def prestavi_v_1kvadrant_V2(sprehod): '''Prestavi sprehod, podan kot seznam parov koordinat, v 1kvadrant''' # s pomočjo izpeljanih seznamov min_x = min(x for x, _ in sprehod) min_y = min(y for _, y in sprehod) return [(x - min_x, y - min_y) for x, y in sprehod]
Sestavite funkcijo stevilo_cikcakastih(zac, kon)
, ki vrne število
vseh cik-cakastih sprehodov med točkama zac
in kon
. Zgled:
>>> stevilo_cikcakastih((0, 0), (9, 3))
84
>>> stevilo_cikcakastih((0, 0), (0, 0))
1
>>> stevilo_cikcakastih((0, 0), (-1, 0))
0
>>> stevilo_cikcakastih((1, 1), (9, 3))
56
>>> stevilo_cikcakastih((1, -1), (9, 3))
28
Namig: Kam gre lahko prvi korak cik-cakastega sprehoda? Dobro si oglejte zgornji zgled.
def stevilo_cikcakastih(zac, kon): '''Koliko cikcakastih sprehodov je med začetno in končno točko''' (xz, yz), (xk, yk) = zac, kon if zac == kon: return 1 elif xz >= xk or abs(yz - yk) > xk - xz: return 0 else: # gremo lahko gor ali dol return stevilo_cikcakastih((xz + 1, yz + 1), kon) + stevilo_cikcakastih((xz + 1, yz - 1), kon)
Sestavite funkcijo narisi_sprehod(sprehod, izhod)
, ki v datoteko z
imenom izhod
z znaki /
in \
izpiše cik-cakast sprehod, podan z
množico točk sprehod
. Sprehod naj premakne tako, da bo
najbolj levi znak v prvem stolpcu, najvišji pa v prvi
vrstici datoteke.
Sprehod
[(0, 0), (1, 1), (2, 0), (3, -1), (4, -2), (5, -1)]
morate tako izpisati kot:
/\
\
\/
Enako sliko da npr. tudi
[(1, 1), (2, 2), (3, 1), (4, 0), (5, -1), (6, 0)]
sprehod
[(5, -4), (6, -3), (7, -4), (8, -5), (9, -4), (10, -3), (11, -4), (12, -5)]
pa kot:
/\ /\
\/ \
Testni primeri delovanje primerjajo na sledečih cik-cakastih sprehodih:
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
,[(0, 0), (1, -1), (2, -2), (3, -3), (4, -4), (5, -5)]
,[(0, 0), (1, 1), (2, 0), (3, -1), (4, -2), (5, -1)]
[(1, 1), (2, 2), (3, 1), (4, 0), (5, -1), (6, 0)]
[(5, -4), (6, -3), (7, -4), (8, -5), (9, -4), (10, -3), (11, -4), (12, -5)]
Namig:
def narisi_sprehod(sprehod, izhod): '''Na izhodno datoteko nariše sprehod''' sprehod = prestavi_v_1kvadrant(sprehod) # prestavimo vse skupaj v prvi kvadrant # poiščemo maksimalno x in max. y koordinato (velikost "slike") max_x, max_y = sprehod[0] for tockaX, tockaY in sprehod: max_x = max(max_x, tockaX) # manjši od obeh je kandidat za min max_y = max(max_y, tockaY) # izhodna slika je najprej ustrezna matrika (seznam seznamov), sestavljena iz presledkov izhSlika = [] for vr in range(max_y): vrstica = [' '] * (max_x + 1) izhSlika += [vrstica] for i in range(len(sprehod) - 1): (x1, y1), (x2, y2) = sprehod[i], sprehod[i + 1] if y2 - y1 == 1: izhSlika[max_y - y2][x1] = '/' elif y2 - y1 == -1: izhSlika[max_y - y1][x1] = '\\' with open(izhod, 'w') as f: for vrstica in izhSlika: izpVrstica = ''.join(vrstica) # združimo (zlepimo) vse znake v vrstici print(izpVrstica, file=f) def narisi_sprehodV2(sprehod, izhod): '''Na izhodno datoteko nariše sprehod''' # uporaba izpeljanih seznamov sprehod = prestavi_v_1kvadrant(sprehod) # prestavimo vse skupaj v prvi kvadrant # poiščemo minimalno x in min. y koordinato max_x, max_y = max(x for x, _ in sprehod), max(y for _, y in sprehod) # izhodna slika je najprej ustrezna matrika (seznam seznamov), sestavljena iz presledkov izhSlika = [[' ' for i in range(max_x + 1)] for j in range(max_y)] for i in range(len(sprehod) - 1): (x1, y1), (x2, y2) = sprehod[i], sprehod[i + 1] if y2 - y1 == 1: izhSlika[max_y - y2][x1] = '/' elif y2 - y1 == -1: izhSlika[max_y - y1][x1] = '\\' with open(izhod, 'w') as f: for vrstica in izhSlika: print(''.join(vrstica), file=f)
Na izlet v Hrčkovo deželo se je odpravilo nekaj družin. Seznam udeležencev izleta je podan v obliki seznama nizov priimkov in imen, ločenih z vejicami. Seveda ima lahko neka oseba več imen ali več priimkov, drugih znakov v imenih (npr. vezaj) pa ni. Primer seznama:
udelezenci = ['Novak, Janez Peter', 'Novak, Ana', 'Kovač Novak, Meta', 'Kovač, Petra']
Sestavi funkcijo vrniImePriimek(oseba)
, ki za dani niz oseba
vrne par
(ime, priimek)
Primeri:
>>> vrniImePriimek('Novak, Janez')
('Janez', 'Novak')
>>> vrniImePriimek('Kovač Novak, Matej')
('Matej', 'Kovač Novak')
>>> vrniImePriimek('Gott Hell, Ana Jana')
('Ana Jana', 'Gott Hell')
def vrniImePriimek(niz): '''Niz razbijemo na ime in priimek - ločilo je vejica''' s = niz.split(',') return (s[1].strip(), s[0].strip())
Družine bi se rade posedle za mize tako, da bodo ob isti mizi sedeli
člani iste družine. Napišite funkcijo razpored_po_mizah(udelezenci)
, ki
naredi slovar, katerega ključi so priimki, vrednosti pa množice imen oseb
iste družine. (Osebi sta člana iste družine, ko imata povsem enaka priimka.)
Primer:
>>> razpored_po_mizah(['Novak, Janez', 'Kovač, Franc', 'Kovač, Jožefa', 'Novak, Micka', 'Kovač Novak, Matej'])
{'Novak': {'Janez', 'Micka'}, 'Kovač Novak': {'Matej'}, 'Kovač': {'Franc', 'Jožefa'}}
def razpored_po_mizah(udelezenci): '''Vrne slovar z razporeditvijo po mizah''' mize = dict() for oseba in udelezenci: (ime, priimek) = vrniImePriimek(oseba) osebe = mize.get(priimek, set()) # iz slovarja dobimo množico oseb, ki že sedijo za mizo oz. prazno množico osebe.add(ime) # dodamo osebo k mizi mize[priimek] = osebe # sedaj pri družini priimek sede te osebe return mize
Organizator izleta se je odločil, da bo poiskal najbolj popularno ime.
Če ima neka oseba več imen (npr. 'Kovač, Ana Beti'
), štejemo vsako
komponento posebej. Napišite funkcijo popularno_ime(udelezenci)
, ki
vrne seznam najbolj popularnih imen, urejenih po abecedi. (Seznam ima
več elementov le v primeru, ko je na vrhu popularnosti več imen.)
Primer:
>>> popularno_ime(['Horvat, Ivan Jožef', 'Hočevar, Franc', 'Horvat, Franc', 'Novak, Jožef', 'Novak, Mici'])
['Franc', 'Jožef']
def popularno_ime(udelezenci): '''Vrne seznam najbolj popularnih imen''' števciImena = dict() for oseba in udelezenci: (ime, priimek) = vrniImePriimek(oseba) komponente = ime.split() # ime razbijemo na dele for k in komponente: # povečamo števce vseh imen števciImena[k] = števciImena.get(k, 0) + 1 najPogostost = max(števciImena.values()) # kateri števec je največji # seznam imen s to največjo pogostostjo kateraImena = [] for ime, frekvenca in števciImena.items(): if frekvenca == najPogostost: kateraImena.append(ime) kateraImena.sort() # seznam imen mora biti urejen po abecedi return kateraImena def popularno_imeV2(udelezenci): '''Vrne seznam najbolj popularnih imen''' # uporaba izpeljanih seznamov števciImena = dict() for oseba in udelezenci: (ime, priimek) = vrniImePriimek(oseba) komponente = ime.split() # ime razbijemo na dele for k in komponente: # povečamo števce vseh imen števciImena[k] = števciImena.get(k, 0) + 1 m = max(števciImena.values()) # kateri števec je največji kateraImena = [ime for ime, frekvenca in števciImena.items() if frekvenca == m] # seznam imen s to pogostostjo kateraImena.sort() # seznam imen mora biti urejen po abecedi return kateraImena
Napišite funkcijo morda_sorodnika(prva_oseba, druga_oseba)
, ki za dve
osebi, podani z nizoma oblike 'priimki, imena'
, vrne True
, če se ujemata
v vsaj enem od priimkov (in False
sicer). Primer:
>>>> morda_sorodnika('Kovač Novak, Ana', 'Novak, Anja')
True
>>>> morda_sorodnika('Kovač Novak, Ana', 'Novak Novak, Anja')
True
>>>> morda_sorodnika('Kovač, Ana', 'Novak, Ana')
False
def morda_sorodnika(prva_oseba, druga_oseba): '''Sta osebi morda sorodnika''' _, priimek_p = vrniImePriimek(prva_oseba) # imena sploh ne potrebujemo, zato _ _, priimek_d = vrniImePriimek(druga_oseba) priimki_d = priimek_d.split() # vsi deli priimka for priimek in priimek_p.split(): if priimek in priimki_d: # našli smo ujemanje v delu return True return False
Napišite funkcijo rodbina(oseba, udelezenci)
, ki vrne seznam oseb (skupaj
z osebo oseba
), ki so morda sorodniki dane osebe, ali pa morda sorodniki
morebitnih sorodnikov dane oseba ali pa morda sorodniki morebitnih sorodnikov
morebitnih sorodnikov danes osebe itn. Seznam naj bo urejen po abecedi.
Primer:
>>> udelezenci = ['A, a', 'A B, b', 'C D, c', 'C A, c', 'Y, x']
>>> rodbina('A, x', udelezenci)
['A, x', 'A, a', 'A B, b', 'C A, c', 'C D, c']
def rodbina_rek(nasi, vasi): '''Vrne seznam tistih iz seznama vasi, ki so morda sorodniki tistih iz nasi''' novi = [] # katere osebe bomo dodali na novo ostanek = [] # kateri del seznama vasi moramo še pregledati (kateri ne bodo neosredno sorodniki tistih iz nasi) for v in vasi: # pregledamo vse kandidate za sorodnike for n in nasi: # je v morda sorodnik komu iz nasi if morda_sorodnika(n, v): # če je, v dodamo med nove in gremo na naslednjega kandidata v vasi novi += [v] break else: # če v ni sorodnik nikomur (for se je izvedel do konca), ga bomo pogledali ali je sorodnik sorodnikov ostanek += [v] # ti bodo morda sorodniki sorodnikov ... if novi == []: # če v tem pregledu nismo dodali nikogra, so vsi sordniki že v nasi return nasi else: return rodbina_rek(nasi + novi, ostanek) # dodamo nove in zaradi tega pregledamo, če so v ostanek sorodniki teh dodanih def rodbina(oseba, udelezenci): '''Vrne seznam oseb (skupaj z osebo oseba), ki so morda sorodniki dane osebe, ali pa morda sorodniki morebitnih sorodnikov ... dane oseba''' return sorted(rodbina_rek([oseba], udelezenci))
Slovar lahko v Pythonu predstavimo s slovarjem – presenetljivo, kajne? Natančneje, ključi v slovarju so besede, pripadajoče vrednosti pa so množice vseh možnih prevodov. Na primer:
{'je': {'is', 'eats'}, 'kosilo': {'lunch'},
'mama': {'mother', 'mum', 'mummy'}}
Sestavite funkcijo obratni(slov)
, ki vrne obratni slovar danega
slovarja slov
.
>>> obratni({'je': {'is', 'eats'}, 'žre': {'bugs', 'eats'}})
{'bugs': {'žre'}, 'eats': {'je', 'žre'}, 'is': {'je'}}
def obratni(slov): '''Vrne obratni slovar''' obrat = {} for beseda, prevodi in slov.items(): for prevod in prevodi: besedePrevoda = obrat.get(prevod, set()) # obstoječi prevodi ali nova množica besedePrevoda.add(beseda) obrat[prevod] = besedePrevoda # popraviomo ali na novo postavimo eleemnt v slovar return obrat
Sestavite funkcijo nedvoumne_in_dvoumne(slov)
, ki vrne par dveh množic:
v prvi naj bodo vse besede iz slovarja slov
, ki imajo natanko en možen
prevod, v drugi pa vse tiste, ki jih imajo več.
>>> nedvoumne_in_dvoumne({'je': {'is', 'eats'}, 'kosilo': {'lunch'}, 'solata': {'salad'}}
({'kosilo', 'solata'}, {'je'})
def nedvoumne_in_dvoumne(slov): '''Vrne dv množici - prvo besede z enim prevodom in drugo vse ostale ''' nedvoum, dvoum = set(), set() for beseda, prevodi in slov.items(): if len(prevodi) == 1: nedvoum.add(beseda) else: dvoum.add(beseda) return nedvoum, dvoum
Sestavite funkcijo vsi_mozni_prevodi(slov, stav)
, ki vrne množico
vseh možnih “prevodov” danega stavka stav
glede na dani slovar slov
.
Stavek je niz, sestavljen iz besed, ločenih s presledki. Če besede ni v
slovarju, naj v prevodu ostane taka, kakršna je.
Namig: sestavite še pomožno funkcijo, ki namesto niza stav
sprejme
seznam besed.
def prevodi_pomozna(slov, besede): '''Vrne seznam, kjer so elementi seznami besed, ki predstavljajo možen prevod''' if len(besede) == 0: return [[]] else: vsi_prevodi = [] prevodi = slov.get(besede[0], {besede[0]}) prevodi_preostanka = prevodi_pomozna(slov, besede[1:]) for prevod in prevodi: for prevod_preostanka in prevodi_preostanka: vsi_prevodi.append([prevod] + prevod_preostanka) return vsi_prevodi def vsi_mozni_prevodi(slov, stav): '''Vrne seznam vse možnih prevodov''' besede = stav.split(' ') # razdelimo stavek na besede prevodi = prevodi_pomozna(slov, besede) #Seznam prevodov množicaPrevodov = set() for enPrevodSeznam in prevodi: enPrevod = ' '.join(enPrevodSeznam) # besede združimo s presledki množicaPrevodov.add(enPrevod) return množicaPrevodov
Sestavite funkcijo preberi(vhod)
, ki prebere datoteko z imenom vhod
in vrne slovar, zapisan v njej. Slovar je v datoteki predstavljen tako,
da je vsaka beseda v svoji vrstici, pod njo pa so v vrsticah, ki se
začnejo z znakom -
, zapisani njeni prevodi. Na primer, v datoteki
je
- is
- eats
kosilo
- lunch
mama
- mother
- mum
- mummy
je zapisan ravno slovar
{'je': {'is', 'eats'}, 'kosilo': {'lunch'},
'mama': {'mother', 'mum', 'mummy'}}
Predpostavite lahko, da je vhodna datoteka vedno zgornje oblike.
def preberi(vhod): '''Iz datoteke sestavi slovar prevodov''' slov = {} for line in open(vhod): if line[0] == '-': # gre za prevod slov[beseda].add(line[2:].strip()) # znebimo se še - in presledka else: beseda = line.strip() # nopva beseda, ki so prevajamo slov[beseda] = set() return slov
Primož rad bere knjige. Doma ima polne police samih dobrih strokovnih
in leposlovnih knjig. Prijatelji si pri njem pogosto sposojajo knjige.
Primož za vsako knjigo vodi evidenco o tem, komu jo je posodil. Podatke
hrani v slovarju, kjer so ključi oznake knjig (nizi), vrednosti pa so
seznami imen prijateljev (prav tako nizi), ki so si sposodili to knjigo,
v kronološkem vrstnem redu. Tisti, ki ima knjigo trenutno pri sebi, je
na zadnjem mestu v seznamu. Če ima Primož knjigo trenutno doma, potem
je na zadnjem mestu v slovarju vrednost None
. Primer:
evidenca_1 = {
'hpotter1': ['Cilka', 'Bojan', 'Samo'],
'hpotter2': ['Bojan', 'Cilka', None],
'agot': ['Cilka', 'Špela', 'Bojan'],
'acok': ['Samo', None],
'vrabec90': ['Klemen', 'Bojan'],
'vidav10': [None]
}
Napišite funkcijo imam_doma(evidenca)
, ki sprejme slovar, kot je
opisan zgoraj, in vrne množico vseh knjig, ki jih ima Primož v tem
trenutku doma. Zgled:
>>> imam_doma(evidenca_1)
{'hpotter2', 'acok', 'vidav10'}
def imam_doma(evidenca): doma = set() for k, v in evidenca.items(): if v[-1] is None: doma.add(k) return doma
Primož bi rad poznal za vsakega prijatelja množico knjig, ki jih ima
ta prijatelj trenutno izposojene. Napišite funkcijo kdo_kaj(evidenca)
,
ki sprejme slovar, kot je opisan zgoraj, in vrne slovar, kjer so ključi
imena prijateljev, vrednosti pa množice knjig, ki jih imajo ti v tem
trenutku sposojene. Zgled:
>>> kdo_kaj(evidenca_1)
{'Samo': {'hpotter1'}, 'Bojan': {'agot', 'vrabec90'}}
def kdo_kaj(evidenca): trenutno = {} for k, v in evidenca.items(): kdo = v[-1] if kdo is None: continue if kdo not in trenutno: trenutno[kdo] = set() trenutno[kdo].add(k) return trenutno
Primoža zanima, kaj njegovi prijatelji radi berejo. Sestavite funkcijo
zgodovina(evidenca, ime)
, ki sprejme slovar, kot je opisan zgoraj, in
ime enega od prijateljev. Funkcija naj vrne množico vseh knjig, ki jih
je imel prijatelj z imenom ime
kadarkoli izposojene. Zgled:
>>> zgodovina(evidenca_1, 'Bojan')
{'hpotter2', 'hpotter1', 'agot', 'vrabec90'}
def zgodovina(evidenca, ime): malha = set() for k, v in evidenca.items(): if ime in v: malha.add(k) return malha
Primoža zanima, kako strastni bralci so njegovi prijatelji. Napišite
funkcijo statistika(evidenca)
, ki sprejme slovar, kot je opisan zgoraj
in vrne nov slovar, kjer so ključi imena vseh prijateljev, ki so si pri
Primožu kadarkoli izposodili kakšno knjigo, vrednost vsakega ključa pa
je število različnih knjig, ki si jih je izposodil ta prijatelj. Zgled:
>>> statistika(evidenca_1)
{'Špela': 1, 'Cilka': 3, 'Bojan': 4, 'Samo': 2, 'Klemen': 1}
def statistika(evidenca): drugovi = set() for v in evidenca.values(): drugovi.update(v) if None in drugovi: drugovi.remove(None) return {druze: len(zgodovina(evidenca, druze)) for druze in drugovi}
Sestavite funkcijo palindrom(niz)
, ki vrne True
kadar je niz
palindrom, in False
sicer.
def palindrom(niz): return niz == niz[::-1]
Pravimo, da je beseda praktično palindrom, če ji je treba zbrisati natanko
eno črko, da bi postala palindrom. Primer je beseda kolo
, ki ji
moramo zbrisati črko k
, pa postane palindrom olo
.
Sestavite funkcijo prakticno_palindrom(niz)
, ki preveri, ali je niz
priktično palindrom. Vse znake (tudi presledke) v besedi obravnavamo enako.
def prakticno_palindrom(niz): # za vsak i poskusimo izpustiti črko na i-tem mestu for i in range(len(niz)): # če smo dobili palindrom, končamo if palindrom(niz[:i] + niz[i + 1:]): return True # če je zanka prišla do konca, palindroma nismo našli return False
Pravimo, da je beseda skoraj palindrom, če ji je treba dodati ali izbrisati natanko eno črko oziroma zamenjati natanko eno črko z drugo, da bi postala palindrom. Primeri:
robot
, kjer moramo t
zamenjati z r
,jana
, kjer moramo na konec dodati j
.Sestavite funkcijo skoraj_palindrom(niz)
, ki preveri, ali je niz
skoraj palindrom. Vse znake (tudi presledke) v besedi obravnavamo enako.
def skoraj_palindrom(niz): # Odstranjevanje in dodajanje črk preverimo s funkcijo prakticno_palindrom. # Razmislite, zakaj smo s tem pokrili tudi dodajanje ene črke. if prakticno_palindrom(niz): return True # Za vsak i poskusimo črko na i-tem mestu nadomestiti s pravilno. for i in range(len(niz)): if palindrom(niz[:i] + niz[-i - 1] + niz[i + 1:]): return True # Če je zanka prišla do konca, palindroma z zamenjavo ene črke nismo našli. return False
Sestavite funkcijo je_prestopno(leto)
, ki vrne True
, kadar je leto
prestopno, in False
, kadar ni.
def je_prestopno(leto): return leto % 4 == 0 and leto % 100 != 0 or leto % 400 == 0
Sestavite funkcijo stevilo_dni(mesec, leto)
, ki vrne število dni danega
meseca (podanega s številom med 1 in 12) v danem letu.
def stevilo_dni(mesec, leto): if mesec == 2 and je_prestopno(leto): return 29 elif mesec == 2: return 28 elif mesec == 4 or mesec == 6 or mesec == 9 or mesec == 11: return 30 else: return 31
Sestavite funkcijo je_veljaven_datum(dan, mesec, leto)
, ki vrne True
natanko tedaj, kadar dan
, mesec
in leto
določajo veljaven datum
(torej mesec
mora biti število med 1 in 12, dan
pa mora ustrezati dnevu
v tem mesecu).
def je_veljaven_datum(dan, mesec, leto): return 1 <= mesec <= 12 and 1 <= dan <= stevilo_dni(mesec, leto)
http://lusy.fri.uni-lj.si/ucbenik/book/1205/index14.html
Naslednja funkcija naj bi vrnila število elementov tabele a
, ki
so manjši od x
, vendar vsebuje napake. Popravi jo.
def kolikoManjsih(a, x):
n = len(a)
koliko = 0
for i in xrange(1, n):
if a[i] != x:
koliko = 1
def kolikoManjsih(a, x): n = len(a) koliko = 0 for i in range(0, n): if a[i] < x: koliko += 1 return koliko