Napiši funkcijo drugi_najvecji(tab), ki vrne drugi največji element v tabeli tab.
V primeru, da je tabela prazna, vrni None.
Če pa ima tabela samo en element, prav tako vrni None.
Predvidevaš lahko, da so elementi v tabeli različni.
Nalogo reši tako, da ne spremeniš tabele. Prav tako ne smeš uporabiti funkcije max!
Napiši funkcijo drugi_najvecji1(tab), ki vrne drugi največji element v tabeli tab.
Kot prej, v primeru, da je tabela prazna, ali
če ima tabela samo element, vrni None.
Predvidevaš lahko, da so elementi v tabele različni.
Nalogo reši z uporabo metod na tabelah in funkcije max, a brez uporabe zank.
Število je popolno, če je enako vsoti vseh svojih pravih deliteljev (razen samega sebe, ampak vključno z 1). Primer popolnega števila je 28, ki ga delijo 1, 2, 4, 7 in 14. Če števila seštejemo, spet dobimo števio 28. Recimo, da 1 ni popolno število.
Napiši funkcijo popolna(sez_stevil), ki sprejme tabelo števil in vrne tabelo števil,
ki vsebuje samo takšna števila iz sez_stevil, ki so popolna.
Na Najboljši TV je prava zmešnjava (kar za najnovejšo TV v Sloveniji niti ni tako nenavadno). Le še 5 minut do začetka oddaje Izbiramo najlepšega bika Slovenije. Težav pa cel kup.
Prva težava je, da je na vseh tabelah naveden napačni vrstni red imen bikov. Režiser na vsak način poskuša prepričati voditeljski par, da ni nič narobe, le od spodaj navzgor naj bereta razvrstitev. A kljub temu, da sta (po njunem mnenju) daleč najbolj inteligentna TV voditelja v Sloveniji, se bojita, da bo to zanju pretežka naloga.
Zato moraš hitro napisati funkcijo obrni_tabelo(tabela_bikov), ki bo
vrnila novo tabelo teh imen v obratnem vrstnem redu.
Primer:
>>> obrni_tabelo(['Bukso', 'Hitri', 'Šeko', 'Lisko'])
['Lisko', 'Šeko', 'Hitri', 'Bukso']
Pozor, ker moraš vrniti novo tabelo, uporaba metode reverse ne bo
primerna! Prav tako ni dovoljena uporaba rezanja (podtabel).
Tabela bikov je sedaj urejena. A kaj, ko so se na tabelo prikradle tudi krave
(na TV sumijo, da gre za podtalno delovanje tet iz ospredja). Zato se bodo
pritožili na MCSodišče. A ura je neizprosna, ustrezno tabelo potrebujejo
takoj. Na srečo je najomiljeni voditelj z vso svojo avtoriteto ugotovil, da
je krave zlahka prepoznati, saj se vsa njihova imena končajo z 'a'. Ker
želijo ohraniti dokaze, morajo tabelo s pomešanimi kravami ohraniti. Zato
sestavi funkcijo odstrani_krave(tabela), ki vrnila novo tabelo teh imen
brez krav. Biki morajo ohraniti svoj vrstni red.
Primera:
>>> odstrani_krave(['Liska', 'Šeko', 'Hitri', 'Buksa'])
['Šeko', 'Hitri']
>>> odstrani_krave(['Bukso', 'Hitri', 'Šeko', 'Lisko'])
['Bukso', 'Hitri', 'Šeko', 'Lisko']
Težav pa še ni konec. Vse to prekladanje tabel je povzročilo, da so sedaj
določena imena v seznamu navedena večkrat. Zato napiši funkcijo
odstrani_ponovljene(tabela), ki vrne novo tabelo, ki ne vsebuje ponovitev
imen. Pri ponovljenih imenih ohrani le prvo pojavitev.
Primer:
>>> odstrani_ponovljene(['Lisko', 'Šeko', 'Šeko', 'Šeko', 'Hitri', 'Bukso', 'Lisko'])
['Lisko', 'Šeko', 'Hitri', 'Bukso']
Namig: Kaj vrne 'bla' in ['blu', 'ble', 'bla', 'blu']?
Četa je najdaljše možno strnjeno podzaporedje v dani tabeli števil z določeno lastnostjo. Če je zaporedje naraščajoče (vsak naslednji element podzaporedja je večji), govorimo o naraščajočih četah, če je nepadajoče (torej je vsak naslednji element večji ali enak) o nepadajočih četah, če je vsak element manjši, imamo padajočo četo, kadar je vsak naslednji element manjši ali enak pa nenaraščajočo četo ...
Celotna tabela je tako sestavljena iz več zaporednih čet. Predpostavili bomo,
da bomo vedno upoštevali čete iste vrste. Tako v tabeli
[2,5,7,1,45,7,7,15] najdemo kar 4 naraščajoče
čete ((2,5,7), (1,45), (7) in (7,15)),
tabela [3,5,8,10,12] pa je sestavljena iz ene same naraščajoče čete.
Po drugi strani pa v tabeli
[2,5,7,1,45,7,7,15] najdemo kar 6 padajočih
čet ((2), (5), (7, 1), (45, 7), (7) in (15)) ali 5 nenaraščajočih
čet ((2), (5), (7, 1), (45, 7, 7) in (15))
Sestavite funkcijo narascajoc(tabela), ki preveri, ali elementi tabele
tabela tvorijo naraščajoče zaporedje. Pomagajte si s primeri:
>>> narascajoc([])
True
>>> narascajoc([1, 2, 5, 8, 12, 35])
True
>>> narascajoc([3, 5, 5])
False
>>> narascajoc([2, 6, 4, 8, 9, 6])
False
Sestavi funkcijo st_nepadajocih_cet(tabela), ki v dani številski tabeli prešteje, iz
koliko nepadajočih čet je sestavljena. Nepadajoča četa je najdaljša možna nepadajoče urejena
podtabela, ali še enostavneje: dokler se zaporedni elementi tabele
ne zmanjšujejo, so v isti četi.
>>> st_nepadajocih_cet([])
0
>>> st_nepadajocih_cet([6])
1
>>> st_nepadajocih_cet([1, 3, 4, 7, 23, 56, 81])
1
>>> st_nepadajocih_cet([1, 2, 2, 6, 2, 3, 7, 5, 2, 3, 8])
4
Sestavi funkcijo st_narascajocih_cet(tabela), ki v dani tabeli števil prešteje,
iz koliko naraščajočih čet je
sestavljena. Naraščajoča četa je najdaljši možen naraščajoče urejen podtabela, ali še
enostavneje: dokler zaporedni elementi tabele naraščajo, so v isti četi.
>>> st_narascajocih_cet([])
0
>>> st_narascajocih_cet([6])
1
>>> st_narascajocih_cet([1, 3, 4, 7, 23, 56, 81])
1
>>> st_narascajocih_cet([1, 2, 2, 6, 2, 3, 7, 5, 2, 3, 8])
5
Sestavite funkcijo dolzina_najdaljse_narascajoce_cete(tabela), ki ugotovi,
kakšna je dolžina najdaljše čete v tabeli tabela.
>>> dolzina_najdaljse_narascajoce_cete([])
0
>>> dolzina_najdaljse_narascajoce_cete([2, 5, 7, 10])
4
>>> dolzina_najdaljse_narascajoce_cete([1, 3, 6, 3, 8, 8, 10, 12])
3
Sestavite funkcijo narascajoce_cete(tabela), ki vrne tabelo vseh naraščajočih čet, ki tvorijo
tabelo tabela.
>>> narascajoce_cete([1, 3, 6, 3, 8, 8, 10, 12])
[[1, 3, 6], [3, 8], [8, 10, 12]]
Butalci vsako leto priredijo polžje dirke. Pomagajte jim pri organizaciji.
Tekmovalnega polža opišemo s tremi parametri: starostjo, težo in velikostjo. Faktor njegove tekmovalne sposobnosti opisuje takšna formula: , pri čemer velja manj je bolje (manjša kot je vrednost faktorja, boljši je polž).
Med vsemi polži želimo poiskati najboljšega. Napišite funkcijo
najboljsi(polzi), ki sprejme tabelo opisov polžev polzi (tabela trojčkov
[starost, teža, velikost]) in vrne faktor za najboljšega polža,
na dve decimalni mesti natančno.
>>> najboljsi([[5, 6, 72], [4, 17, 77], [14, 21, 22], [17, 36, 64], [13, 29, 23]])
16.39
Butalski polži se premikajo samo v štirih smereh: sever, jug, vzhod in
zahod, kar v koordinatnem sistemu pomeni gor, dol, desno in levo.
V vsakem koraku se premaknejo za eno enoto, lahko pa tudi mirujejo.
Njihove premike zato lahko opišemo s tabelo, ki vsebujejo poljubno
zaporedje črk 'S', 'J', 'V', 'Z' in 'M'.
Napišite funkcijo pot(premiki), ki sprejme tabelo, ki opisuje premike polža
in pove, kako dolgo pot je opravil polž polž in kako daleč (zračne razdalje) je prilezel. Rezultat naj bo
dan v obliki para celo in dec. število, kjer je slednje zaokroženo na dve decimalni mesti.
>>> pot(['M', 'J', 'V', 'S', 'S', 'M'])
(4, 1.41)
Po končanem tekmovanju so znane poti vseh polžev. Velja, da je zmagovalec
tisti polž, ki je prilezel najdlje od začetka (seveda pa si lahko prvo mesto deli
več zmagovalcev, če so prelezli isto razdaljo). Pri tem seveda
doseženo razdaljo računamo zaokroženo, kot pri zgornji nalogi!
Napišite funkcijo
zmagovalci(poti), ki sprejme tabelo poti vseh polžev poti ter izračuna, koliko
polžev je osvojilo prvo nagrado.
>>> zmagovalci([['S', 'Z', 'S'], ['M', 'Z', 'V'], ['J', 'J', 'Z'], ['J', 'J', 'Z'], ['S', 'S', 'M']])
3
Namig: pomagaj si s funkcijo iz prejšnje naloge.
Pri reševanju te naloge (razen prvih dveh) uporabljamo tudi "rezanje" (slicing). Npr. s tab[1:] dobimo tabelo, ki je enaka tabeli tab, le da nima prvega elementa.
V tabeli imamo podatke o prilivih in odlivih s tekočega računa. Pozitivna števila predstavljajo priliv (polog denarja), negativna pa dvig. Vsak element tabele predstavlja en dan. Če na nek dan ni prilivov ali dvigov, je vrednost v tabeli 0. Privzemite, da je na začetku stanje na računu 0.
Sestavite funkcijo koncno_stanje(spremembe), ki iz dane tabele
prilivov in odlivov izračuna končno stanje.
Pri rešitvi ne uporabi zanke neposredno v kodi te funkcije.
Sestavite funkcijo stanja(spremembe), ki iz dane tabele
prilivov in odlivov ustvari tabelo vmesnih stanj na računu.
Privzemite, da je na začetku stanje na računu 0. To naj bo prva "sprememba" v tabeli
>>> stanja([10, -5, 20, -6])
[0, 10, 5, 25, 19]
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 (uporabi rezanje)
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. Namig: Pomagaj si s funkcijami iz prejšnjih nalog.
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.
Namig: Pomagaj si s funkcijami iz prejšnjih nalog ter z metodo index.
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.
Tu potrebuješ rezanje!
Sestavite funkcijo najvecja_razlika(spremembe), ki poišče največji
relativni priliv. Z drugimi besedami, poišče največjo vrednost, ki jo
zavzame vsota poljubne strnjene podtabele.
Tako na primer najvecja_razlika([10, -13, 3, 20, -2, 5]) vrne
3 + 20 - 2 + 5 = 26.
Če je tabela spremembe prazna, naj funkcija vrne None.
Namig: verjetno bo potrebno preveriti vse možne podtabele!
Napišite funkcijo pascal(n), ki vrne tabelo prvih n vrstic Pascalovega
trikotnika. Vrstice naj bodo dane kot tabele. Če je n enak 0, naj funkcija vrne
prazno tabelo.
>>> pascal(6)
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1]]
V Republiki Banana zaradi utrujenosti in pomanjkanja koncentracije kamionisti (slovensko - vozniki kamionov Zato pet minut za učenje slovenčine) vse pogosteje povzročajo nesreče. Na vladi so se odločili, da bodo sprejeli zakone, ki bodo uredili problematiko preutrujenih kamionistov. Najprej pa morajo analitiki preučiti njihove navade. V ta namen so pridobili podatke o kamionistih. Za vsakega imajo podano tabelo, v kateri so shranjene prevožene razdalje po posameznih dnevih. Število 0 pomeni, da je kamionist tisti dan počival.
Primer: Tabela
[350, 542.5, 0, 602, 452.5, 590.5, 0, 248]
pomeni, da je kamionist prvi dan prevozil 350 km, drugi dan je prevozil 542.5 km, tretji dan je počival itd.
Sestavite funkcijo pocitek_in_povprecje(voznja), ki kot argument
dobi zgoraj opisano tabelo (prevožene razdalje po posameznih dnevih)
in vrne par števil. Prvo število naj bo število dni, ko je kamionist
počival. Drugo število naj bo na eno decimalko zaokrožena (round(x, 1))
povprečna dnevna prevožena razdalja, pri
čemer upoštevamo samo tiste dneve, ko ni počival. Predpostavite lahko,
da kamionist vsaj en dan ni počival. Primer:
>>> pocitek_in_povprecje([200, 300, 0, 100])
(1, 200.0)
Kamionist je torej enkrat počival. Ob dnevih, ko ni počival, pa je v povprečju prevozil 200 km.
Napišite funkcijo primerjaj(prvi, drugi), ki primerja vožnjo dveh
kamionistov. Funkcija kot argumenta dobi dve enako dolgi tabeli
prvi in drugi, ki opisujeta vožnjo dveh kamionistov, ki sta se
podala na isto pot. Funkcije naj sestavi in vrne novo tabelo, v kateri
je za vsak dan zapisano, kdo je do tega dne skupaj prevozil večjo
razdaljo:
1, če je bil to 1. kamionist; 2, če je bil to 2. kamionist in
0, če sta oba prevozila enako razdaljo. Primer:
>>> primerjaj([200, 300, 100], [200, 200, 300])
[0, 1, 2]
>>> primerjaj([500, 100, 100], [100, 200, 200])
[1, 1, 1]
Vlada je uzakonila naslednja pravila: * Povprečna prevožena razdalja v treh zaporednih dneh ne sme biti več kot 500 km. (Štejemo tudi dneve, ko je kamionist počival.) * Kamionist ne sme brez počitka voziti več kot 5 dni v zaporedju.
Ker so ugotovili, da so kamionisti prevečkrat svoje zaporedje skrajšali na dva dni in se s tem dejansko izognili pravilu, so uzakonili še: * Zadnji dan ne sme voziti več kot 500 km. * Povprečje zadnjih dveh dni ne sme biti več kot 500 km.
Sestavite funkcijo po_pravilih(voznja), ki vrne True, če se je
kamionist držal predpisov, in False, če se jih ni.
>>> po_pravilih([50, 200, 300, 20, 100, 60])
False
>>> po_pravilih([600, 200, 0, 300, 300, 0, 600, 600, 400])
False
>>> po_pravilih([600, 600, 0, 600, 600])
False
>>> po_pravilih([600, 600, 0, 200, 600])
False
Podatke za več kamionistov so analitiki združili v eno samo tabelo. Zgled take tabele:
vsi_skupaj = [
[50, 200, 300, 20, 100, 60],
[600, 600, 0, 600, 600, 0, 500, 500],
[600, 200, 0, 300, 300, 0, 600, 600, 400]
]
Sestavite funkcijo preveri_vse(seznam_vozenj), ki dobi kot argument
tabelo kot je zgoraj in vrne tabelo logičnih vrednosti, ki za vsakega
kamionista pove, če je vozil po predpisih. Primer:
>>> preveri_vse(vsi_skupaj)
[False, True, False]
Ko so vožnje vseh kamionistov že tako lepo združene, so se analitiki spravili
računati še to, kakšno je navečje število voženj, ki jih je nekdo opravil,
kakšno je največje število dni počitka ter kakšno je največje in kakšno
najmanjše povprečno število dnevno prevoženih kilometrov (povprečje tako,
kot pri prvi nalogi - štejemo le dneve vožnje). Pri tem upoštevamo samo tiste
kamioniste, ki so vozili po pravilih!
Sestavite funkcijo analitika(seznam_vozenj), ki dobi kot argument
ustrezno tabelo in vrne nabor 4 vrednosti: največ voženj, največ dni počitka,
maksimalno povprečno dnevno prevoženih in minimalno povprečnodnevno
prevoženih kilometrov. Predpostavi, da imamo vsaj enega kamionista, ki je
vozil po predpisih!
Primer (podatki iz prejšnje naloge):
>>> analitika(vsi_skupaj)
(6, 2, 566.7, 566.7)
Sestavite funkcijo prestej(niz), ki prešteje, koliko zašiljenih
oklepajev tj. '<' in '>' je v nizu niz. Primer:
>>> prestej('<abc>>')
3
>>> prestej('a>> x<Y>x <<b')
6
>>> prestej('Koliko oklepajev > in < je v tem nizu?')
2
Pri tem ne smeš uporabiti vgrajene metode count
Niz imenujemo ukleščen, če se začne z predklepajem '<', konča
z zaklepajem '>', vmes pa ni nobenega znaka za zašiljene oklepaje.
Na primer, niz '<Zunaj sije sonce.>' je ukleščen niz.
Sestavite funkcijo uklescen(niz), ki preveri, ali je niz niz ukleščen.
Primer:
>>> uklescen('<Zunaj sije sonce.>')
True
>>> uklescen('< <3 >')
False
>>> uklescen('Zunaj sije sonce.')
False
Znaš nalogo rešiti brez zanke v telesu funkcije uklescen? Seveda pa si lahko
pomagaš s funkcijo prestej iz prejšnje podnaloge.
Sestavite funkcijo sklop(niz1, niz2), ki prejme dva ukleščena niza
in vrne ukleščeni niz, ki predstavlja njun sklop, ki je tudi ukleščen niz.
Primer:
>>> sklop('<123>', '<456>')
'<123456>'
>>> sklop('<muca>', '<copatarica>')
'<mucacopatarica>'
Sestavite funkcijo razlomi(niz, s), ki kot argumenta prejme
ukleščeni niz niz in tabelo nenegativnih celih števil s ter vrne
tabelo ukleščenih nizov, ki imajo dolžine, naštete v tabele s,
in skupaj tvorijo niz niz.
Primer:
>>> razlomi('<Zunaj sije sonce.>', [2, 7, 8])
['<Zu>', '<naj sij>', '<e sonce.>']
>>> razlomi('<muca copatarica>', [4, 0, 11])
['<muca>', '<>', '< copatarica>']
Predpostavite lahko, da bo vsota števil v tabeli s enaka dolžini
ukleščenega niza niz (če ne štejemo zašiljenih oklepajev).
Sestavite funkcijo celostevilski(sprehod), ki sprejme niz, ki predstavlja
sprehod po celih številih, in vrne število, v katerem se sprehod konča.
Sprehod po celih številih se začne v številu 0, predstavimo pa ga z nizem,
sestavljenim iz znakov + in -, ki pomenita pomik za ena v desno in ena v levo
na številski osi. Na ostale znake v nizu se ne oziramo.
Zgled:
>>> celostevilski('++--#---@++--+-++')
-1
Sestavite funkcijo ravninski(sprehod), ki sprejme niz, ki predstavlja
zaporedje korakov v ravnini, in vrne točko (par dveh števil), v kateri se
sprehod konča.
Sprehod po ravnini se začne v izhodišču, predstavimo pa ga z nizem,
sestavljenim iz črk S, J, V ali Z, ki predstavljajo smeri korakov
(sever, jug, vzhod, zahod). Na ostale znake v nizu se ne oziramo.
Zgled:
>>> ravninski('#ZZZS#')
(-3, 1)
Sestavite funkcijo hitri(tek), ki sprejme niz, ki predstavlja zaporedje
korakov in skokov v ravnini, in vrne točko, v kateri se tek konča.
Tek po ravnini se začne v izhodišču, predstavimo pa ga, tako kot sprehod, z
nizem, sestavljenim iz črk S, J, V ali Z, ki predstavljajo smeri
korakov (sever, jug, vzhod, zahod).
Poleg tega lahko tek vsebuje tudi števke od 1 do 9, ki povedo, koliko
dolg naj bo naslednji korak. Tako niz 5S pomeni skok na sever, dolg 5
korakov. Privzamete lahko, da zaporednih števk v nizu ni, ter da se na ostale
znake v nizu ne oziramo.
Zgled:
>>> hitri('3S4ZJ')
(-4, 2)
V laboratoriju FMF-P1 jim je uspel tehnološki presežek. Sestavili so robota, ki zlahka hodi po stopnicah. Konkurenca na vsak način poskuša diskreditirati ta dosežek. Zato sestavljajo različne čudne kombinacije stopnic in čakajo, kdaj bo robot pri hoji padel, saj lahko robot prehodi le stopnico, ki je visoka največ 20 cm. Ampak spretni študenti praktiki so robota opremili z merilnim sistemom, ki zmeri višino posamezne stopnice, in napisali funkcijo (opaziš, da je lepo skrbno komentirana, kot vsa koda, ki jo pišejo v tem laboratoriju).
def koliko_stopnic(stopnice):
"""Vrne število stopnic, ki jih lahko prehodi robot."""
katera = 0 # indeks stopnice
while katera < len(stopnice):
v = stopnice[katera] # za vsako stopnico vzamemo njeno višino
if v > 20: # ce je visina stopnice previsoka
return katera # koliko stopnic lahko prehodim (ker začnemo z 0, bo OK!)
katera += 1 # naslednja stopnica
# prehodili smo vse!
return len(stopnice)
Na osnovi te kode sestavi funkcijo kako_visoko_pridem(stopnice), ki kot
argument prejme tabelo višin stopnic stopnice rezultat, ki ga vrne, pa
pove, na kakšni višini bo robot po koncu hoje.
Na FRI-P1 pa jim je uspelo izdelati napravo, ki zmoti merilni sistem robota
tako, da meri višine stopnic, merjene od tal (ne od prejšnje stopnice).
Ampak praktiki s FMF se ne dajo. Poleg tega, da robota izpopolnijo, da ima
sedaj nastavljivo maksimalno višino koraka (a žal se ta med hojo ne da
spreminjati), na osnovi prejšnje naloge napišejo funkcijo
kako_visoko(stopnice, korak_robota), ki kot argument prejme tabelo višin
stopnic stopnice, merjenih na "FRI način" in kako visoko se lahko robot
premakne v enem koraku, rezultat, ki ga vrne, pa spet pove, kako visoko
bo robot priplezal.
Primer:
>>> kako_visoko([5, 25, 45, 50, 76, 80, 81], 20)
50
Lojzku je dolgčas, zato se igra z velikimi praznimi škatlami, ki so v
skladišču, v katerem dela. Dimenzije škatel so shranjene v tabeli trojic.
Na primer, trojica (50, 100, 100) predstavlja škatlo, ki je visoka 50 cm
ter široka in dolga 100 cm.
S trojicami delamo tako kot s tabelami, le spreminjati ne moremo elementov.
Torej nam skatla[0] da prvi element iz trojice skatla. Seveda pa lahko trojko tudi
"razpakiramo"
vis, sir, dol = skatla
če je skatla neka trojka.
Sestavite funkcijo stolp(skatle), ki vrne višino najvišjega stolpa, ki ga
lahko sestavimo iz škatel, ne da bi jih obračali. Pri tem ni treba paziti na
stabilnost stolpa.
Primer:
>>>stolp([(50, 100, 100), (60, 30, 50), (40, 40, 40), (10, 30, 10)])
160
Sestavite funkcijo najvisji_stolp(skatle), ki vrne višino najvišjega
stolpa, ki ga lahko sestavimo iz škatel, če jih lahko obračamo. Pri tem še
vedno ni treba paziti na stabilnost stolpa.
Primer:
>>> najvisji_stolp([(50, 100, 100), (60, 50, 50), (40, 40, 40)])
200
(prva škatla ima širino in dolžino večjo od širine, zato jo prevrnemo na bok.)
Sestavite funkcijo gre_notri(skatla1, skatla2), ki vrne True, če škatlo
skatla1 lahko obrnemo tako, da gre v škatlo skatla2, torej da so
dimenzije prve škatle strogo manjše od dimenzij druge škatle.
Primer:
>>> gre_notri((30, 40, 50), (40, 50, 60))
True
>>> gre_notri((30, 50, 40), (40, 50, 60))
True
>>> gre_notri((30, 60, 60), (40, 50, 60))
False
Prevzeli smo podjetje Vsi Enaki. V skladu z imenom podjetja bi radi poskrbeli,
da bodo imeli vsi delavci enako plačo. Ker plače seveda ne moremo jemati
(prepir, jok, izsiljevanje in te reči), je naša naloga napisati
funkcijo enake_place(tab_plac), ki kot argument dobi tabelo s plačami
v gljubih (saj vam je jasno, da se to ne dogaja na našem planetu),
kot rezultat pa vrne, koliko gljubov bo potrebno dodatno zagotoviti.
Primer:
>>> enake_place([5, 8, 6, 4])
9
Znaš nalogo rešiti z vgrajenimi python funkcijami brez uporabe zank?
Sedaj vemo, koliko sredstev bomo potrebovali. A koliko se bo povečala plača posameznika? V tabeli imamo poleg plače še ime posameznega delavca.
Napiši funkcijo imena_s_placami(place), ki sprejme tabelo tabel prikazano na spodnjem primeru
in vrne tabelo tabel s podatki o tem, za koliko se posameznemu delavcu zviša plača.
V izhodni tabeli naj bodo samo delavci, ki se jim plača zviša.
Primer:
>>> imena_s_placami([[5,"Brane"], [8,"Bine"], [6,"Janez"], [4,"Albert"]])
[[3,"Brane"],[2,"Janez"],[4,"Albert"]]
Z RTK 2001.1.1
Predpostavimo, da lahko vse znake, ki jih želimo natipkati, razdelimo v dve skupini: nekatere tipkamo vedno z levo roko, druge pa vedno z desno.
Napisana je funkcija dolzina_najdaljsega_podniza(vhod). Dopolni jo na mestih,
označenih z ###, da bo iz danega niza izračunala in vrnila dolžino takega
najdaljšega podniza, ki ga je mogoče v celoti natipkati z eno samo roko.
def dolzina_najdaljsega_podniza(vhod):
"""Izračuna dolžino najdaljšega podniza v vhodnem nizu."""
trenutna_roka = None
max_z_eno = 0
st_s_trenutno = 0
for crka in vhod:
nova_roka = ###
if nova_roka == trenutna_roka:
# Z isto roko kot doslej natipkamo še en znak več.
st_s_trenutno += 1
elif st_s_trenutno > ###:
# Zamenjamo roko. Mogoče smo z dosedanjo dosegli nov rekord.
max_z_eno = st_s_trenutno
st_s_trenutno = 1
else:
###
trenutna_roka = nova_roka
###
Na voljo imaš funkcijo s_katero_roko(crka), ki zna za vsak znak povedati,
v katero od navedenih dveh skupin spada. Če ga napišemo z levo, nam vrne
niz 'leva', sicer pa niz 'desna'.
Primeri:
Če se a in e tipkata vedno z levo roko, i, o in u pa vedno z desno, je pri nizu aeiou pravilni odgovor:
>>> dolzina_najdaljsega_podniza('aeiou')
3
Podniz iou lahko namreč natipkamo z desno roko.
Poglejmo si še nekaj primerov:
>>> dolzina_najdaljsega_podniza('aaeaiaoaua')
4
Podniz aaea lahko namreč natipkamo z levo roko.
>>> dolzina_najdaljsega_podniza('ouaeauo')
3
Podniz aea lahko namreč natipkamo z levo roko.
>>> dolzina_najdaljsega_podniza('uaoei')
1
Nobenih dveh zaporednih znakov ne moremo natipkati z isto roko.
>>> dolzina_najdaljsega_podniza('iieeoo')
2
V tem primeru lahko niz ii v celoti natipkamo z desno ali pa ee z levo ali pa oo z desno.
Klodovik (papiga) in ne Klodvik (frankofonski kralj)/ bi rad zašifriral svoja besedila, da jih nepoklicane osebe ne bodo mogle prebrati. To stori tako, da najprej v besedilu vse male črke spremeni v velike in odstrani vse znake, ki niso črke. Klodvik vsa pomembna besedila piše v angleščini, zato bomo uporabljali angleško abecedo.
Na primer iz besedila 'Attack at dawn!' dobi besedilo 'ATTACKATDAWN'.
Nato ga zapiše cik-cak v treh vrsticah, kot prikazuje primer:
A...C...D...
.T.A.K.T.A.N
..T...A...W.
Sestavite funkcijo cik_cak(niz), ki vrne trojico nizov (torej tuple) in
sicer prvo, drugo in tretjo vrstico v tem zapisu.
Primer:
>>> cik_cak('Attack at dawn!')
('A...C...D...', '.T.A.K.T.A.N', '..T...A...W.')
Zašifrirano besedilo dobi tako, da najprej prepiše vse znake iz prve vrstice,
nato vse znake iz druge vrstice in na koncu še vse znake iz tretje vrstice. V
zgornjem primeru bi tako dobil 'ACDTAKTANTAW'. Sestavite funkcijo
cik_cak_sifra(niz), ki dobi kot argument niz in vrne zašifrirano besedilo.
Primer:
>>> cik_cak_sifra('Attack at dawn!')
'ACDTAKTANTAW'
Klodovik se zelo razjezi, ko dobi elektronsko pošto v takšni obliki:
Kar sva si obljubljala že leta, si želiva potrditi tudi pred prijatelji in celo
žlahto. Vabiva te na
poročno slovesnost, ki bo
10. maja 2016 ob 15. uri na gradu Otočec. Prijetno druženje bomo
nadaljevali v hotelu Mons. Tjaša in Pavle
Nepopisno mu gre na živce, da je med besedami po več presledkov. Še bolj pa ga nervira, ker so nekatere vrstice precej daljše od drugih. Ker je Klodvik vaš dober prijatelj, mu boste pomagali in napisali funkcije, s katerimi bo lahko olepšal besedila.
Najprej napišite funkcijo razrez(niz), ki kot argument dobi niz in vrne
tabelo besed v tem nizu. Besede so med seboj ločene z enim ali večimi
praznimi znaki: ' ' (presledek), '\t' (tabulator) in '\n' (skok v novo
vrstico). Pri tej nalogi ločilo obravnavamo kot del besede.
Primer:
>>> razrez(' Kakršen\t pastir, \n\ntakšna čreda. ')
['Kakršen', 'pastir,', 'takšna', 'čreda.']
Sedaj, ko že imate funkcijo razrez, bo lažje napisati tisto funckijo, ki
jo Klodovik zares potrebuje. To je funkcija olepsaj_besedilo(niz, sirina),
ki kot argumenta dobi niz in naravno število sirina. Funkcija vrne olepšano
besedilo, kar pomeni naslednje:
sirina znakov (pri čemer znaka
'\n' na koncu vrstice ne štejemo).Predpostavite, da dolžina nobene besede ni več kot sirina in da je niz
neprazen.
Primer:
>>> lepo_besedilo = olepsaj_besedilo(' Jasno in svetlo \t\tna sveti \t\n\nvečer, dobre\t\t letine je dost, če pa je\t oblačno in temno, žita ne bo.', 20)
>>> print(lepo_besedilo)
Jasno in svetlo na
sveti večer, dobre
letine je dost, če
pa je oblačno in
temno, žita ne bo.
V nekem besedilu so odstavki ločeni s praznimi vrsticami. Popravi funkcijo
odstavki(besedilo), ki naj prebere besedilo v nizu in ga vrne kot niz, pri
tem pa, če se kdaj pojavi več zaporednih praznih vrstic, takšno skupino praznih
vrstic nadomesti z eno samo prazno vrstico. Za prazne vrstice štejemo le tiste
vrstice, ki res ne vsebujejo nobenega znaka, niti presledkov. Novo vrstico
označuje '\n'.
def odstavki(besedilo):
"""Skupine praznih vrstic v besedilu nadomesti z eno samo prazno vrstico."""
vrstice = besedilo.split('')
izpis = ''
prejsnja_prazna = False
for vrstica in vrstice:
if vrstica == '' and not prejsnja_prazna:
continue
elif vrstica == '' and prejsnja_prazna:
prejsnja_prazna = True
izpis += vrstica + '\n'
else:
prejsnja_prazna = False
izpis += vrstica + '\n'
return izpis
Primer
>>> odstavki('Danes je lepo, sončno vreme.\n\n\n\nZunaj pojejo ptički.')
'Danes je lepo, sončno vreme.\n\nZunaj pojejo ptički.'
MiniLogo je okrnjena izvedba programskega jezika Logo, ki premore le
štiri ukaze: F, B, R in L. S temi štirimi ukazi upravljamo
želvo. Želva se nahaja v ravnini, ki je opremljena z običajnim
koordinatnim sistemom (prva koordinata narašča proti desni, druga
koordinata pa narašča navzgor). Želva se na začetku nahaja v točki
in gleda navzgor (proti "severu"). Z ukazom F želvi povemo,
naj naredi en korak naprej (v tisti smeri, kamor je trenutno obrnjena).
Z ukazom B povemo, naj naredi želva korak nazaj. Ukaz R pomeni, naj
se želva zavrti v desno (tj. v smeri urinega kazalca) za 90°. Ukaz L pa
pomeni, naj se želva zavrti za 90° v levo (tj. v nasprotni smeri urinega
kazalca).
Program, ki upravlja z želvo, je torej niz v katerem nastopajo zgornji
štirje znaki. Primer: 'FFLFRFRFFFLBRBLBBLF'.
Sestavite funkcijo kam_pa_kam(ukazi), ki kot argument dobi niz
ukazi. Ta niz vsebuje ukaze za želvo, kot je opisano zgoraj. Funkcija
naj izračuna in vrne koordinati tiste točke, kjer se želva ustavi.
>>> kam_pa_kam('LFF')
(-2, 0)
>>> kam_pa_kam('FRFLFRFLFRFLFRF')
(4, 4)
Sestavite funkcijo pot_zelve(ukazi), ki kot argument dobi niz ukazi.
Funkcija naj vrne tabelo točk (tj. urejenih parov koordinat), ki naj
predstavlja pot, ki jo prepotuje želva.
>>> pot_zelve('LFF')
[(0, 0), (-1, 0), (-2, 0)]
>>> pot_zelve('RFRFRFRF')
[(0, 0), (1, 0), (1, -1), (0, -1), (0, 0)]
Želva vedno začne svoj pohod v točki obrnjena proti "severu".
Pot (tj. tabela, ki jo funkcija vrne) bo vedno vsebovala en element več,
kot je skupno število znakov 'F' in 'B' v nizu ukaz.
Sestavite funkcijo sled_zelve(ukazi), ki kot argument dobi niz ukazi.
Funkcija naj vrne tabelo sled, ki predstavlja sled želve (tj. tabela
vseh koordinat, ki jih želva vsaj enkrat obišče na svoji poti). Sled se
od poti razlikuje v tem, da se nobena točka v tabeli sled ne sme
pojaviti več kot enkrat. Pozor: točke, ki jih želva obišče prej, se
morajo tudi v tabeli sled pojaviti prej.
>>> sled_zelve('FFFBBFFFBBFFFBB')
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]
>>> sled_zelve('FBRFBRFBRFBRFBFB')
[(0, 0), (0, 1), (1, 0), (0, -1), (-1, 0)]
Želve, ki živijo v neposredni bližini Černobila, lahko korakajo samo
nazaj in se obračajo samo v levo. Kljub temu pa se izkaže, da lahko
tudi "handicapirana" želva prehodi čisto vsako pot, ki jo lahko prehodijo
običajne želve. Sestavite funkcijo mutant(pot), ki kot argument dobi
tabelo pot, ki predstavlja veljavno pot želve, ki se začne v točki
. Funkcija naj vrne niz ukazov ukazi, ki sme vsebovati le znaka
'L' in 'B'. Želva, ki bo začela svojo pot v točki obrnjena proti
"severu" in bo sledila tem ukazom, bo prehodila natančno tisto pot, ki je
podana kot argument funkcije.
>>> mutant([(0, 0), (-1, 0), (-2, 0)])
'LLLBB'
>>> mutant([(0, 0), (1, 0), (1, -1), (0, -1)])
'LBLLLBLLLB'
Niz, ki ga vrne funkcija mutant, ne sme vsebovati odvečnih rotacij.
Polinome predstavimo s tabelo koeficientov, pri čemer element z indeksom predstavlja koeficient ob (med drugim torej prazna tabela predstavlja ničelni polinom).
Napišite funkcijo odstrani_odvecne_nicle(koeficienti), ki vrne tabelo
koeficienti, v katerem na koncu odstrani odvečne ničle.
Namreč polinom 2x - 3 bi lahko prestavili kot [-3, 2] ali
pa [-3, 2, 0] (torej 0 x^2 + 2x - 3) ali pa [-3, 2, 0, 0, 0, 0].
>>> odstrani_odvecne_nicle([0, 1, 2])
[0, 1, 2]
>>> odstrani_odvecne_nicle([2, 1, 0])
[2, 1]
>>> odstrani_odvecne_nicle([0, 0, 0, 0, 0, 0])
[]
Napišite funkcijo odvod_polinoma(polinom, n), ki za dani polinom vrne
njegov n-ti odvod. Privzeta vrednost za n naj bo 1.
>>> odvod_polinoma([1, 2, 3])
[2, 6],
>>> odvod_polinoma([4, -1, 2, 0, 1], n=2)
[4, 0, 12],
>>> odvod_polinoma([1])
[]
Napišite funkcijo vsota_polinomov(polinom1, polinom2), ki vrne vsoto danih
polinomov. Nastali polinom naj ne vsebuje odvečnih ničel.
>>> vsota_polinomov([1, 2, 3], [5, 6, 7, 8])
[6, 8, 10, 8]
>>> vsota_polinomov([1, 2, 3], [-1, -2, -3])
[]
Naloga s tekmovanja RTK 1999
Iz vesolja pričakuješ signal nezemeljske civilizacije. Utemeljeno lahko pričakuješ, da bo sporočilo poslano v jeziku, ki uporablja angleško abecedo 26 malih črk in zadošča naslednjim pravilom:
Preuredi vrstice funkcije pravo(niz) tako, da bo ugotovila, ali sporočilo
ustreza tem pogojem.
if znak not in dovoljeni_znaki:
prejsnji_znak = znak
return False
def pravo(niz):
return False
return False
return True
dovoljeni_znaki = 'abcdefghijklmnopqrstuvwxyz '
for znak in niz:
if znak == prejsnji_znak:
prejsnji_znak = ''
samoglasniki = ['a','e','i','o','u']
if znak in samoglasniki and prejsnji_znak in samoglasniki:
'''Vrne True, če besedilo v niz ustreza vseh pogojem in False sicer.'''
return False
if prejsnji_znak == 'x' and znak != ' ':
Sporočilo v obliki niza.
True, če niz ustreza vsem pravilom in False sicer.
>>> pravo('we live in same universe')
`True`
>>> pravo('can you hear us')
`False`
Sestavite funkcijo sumniki(niz), ki kot argument dobi niz niz,
vrne pa niz, v katerem so vsi šumniki 'č', 'š', 'ž', 'Č', 'Š' in
'Ž' zamenjani s pripadajočimi znaki brez strešic 'c', 's', 'z',
'C', 'S' in 'Z'. Zgled:
>>> sumniki('Špela nabira rožice.')
'Spela nabira rozice.'
Za prenos kritičnih informacij in za zmanjšanje napak pri prenosu je mednarodna organizacija za civilno letalstvo (ang. International Civil Aviation Organization - ICAO) uvedla mednarodno abecedo za radio-telefonsko črkovanje.
To pomeni, da je vsaki izmed 26 črk angleške abecede priredila besedo, ki se začne s to črko: alfa, bravo, charlie, delta, echo, foxtrot, golf, hotel, india, juliett, kilo, lima, mike, november, oscar, papa, quebec, romeo, sierra, tango, uniform, victor, whiskey, x-ray, yankee, zulu.
Kasneje so to abecedo prevzele NATO in nekatere druge organizacije.
Sestavite funkcijo crkujNATO(besedilo), ki vrne niz, v katerem je
vsaka mala črka iz niza besedilo zamenjana z ustrezno besedo iz zgornje
abecede. Če znak ni mala tiskana črka, naj ostane nespremenjen. Med vsako
besedo oz. nespremenjenim znakom naj bo presledek. Na koncu niza naj ne
bo presledka.
Za pretvorbo uporabite naslednjo tabelo:
['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf',
'hotel', 'india', 'juliett', 'kilo', 'lima', 'mike', 'november',
'oscar', 'papa', 'quebec', 'romeo', 'sierra', 'tango', 'uniform',
'victor', 'whiskey', 'x-ray', 'yankee', 'zulu']
Na primer:
>>> crkujNATO('test')
tango echo sierra tango
>>> crkujNATO('star sem 18 let.')
sierra tango alpha romeo sierra echo mike 1 8 lima echo tango .
Sestavite funkcijo razberiNATO(nizNATO), ki sprejme niz nizNATO črkovan
po NATO standardu in ga pretvori v navadno besedilo. Vsaka črka (torej
beseda) je v nizNATO ločena z enim presledkom.
Predpostavi, da v besedilu ni presledkov in da je besedilo zagotovo pravilno črkovano! Na primer:
>>> razberiNATO('tango echo sierra tango')
test
>>> razberiNATO('sierra tango alpha romeo - sierra echo mike - 1 8 - lima echo tango .')
star-sem-18-let.
Sestavite funkcijo prav_razberiNATO(nizNATO), ki naredi isto kot funkcija
razberiNATO, le da tokrat dopuščamo presledke med besedami.
Če je v originalnem besedilu bil presledek, se seveda v nizNATO pojavijo
trije zaporedni presledki.
Na primer:
>>> prav_razberiNATO('tango echo sierra tango')
test
>>> prav_razberiNATO('sierra tango alpha romeo - sierra echo mike - 1 8 - lima echo tango .')
star-sem-18-let.
>>> prav_razberiNATO('sierra tango alpha romeo sierra echo mike 1 8 lima echo tango .')
star sem 18 let.
Sestavite funkcijo razberiNATODeLux(nizNATO), ki naredi isto kot funkcija
prav_razberiNATO, le da tokrat dopuščamo, da je besedilo napačno črkovano.
Če je besedilo napačno črkovano, naj funkcija vrne niz NAPAKA!
Na primer:
>>> razberiNATODeLux('tango echo sierra tango')
test
>>> razberiNATODeLux('tangice echo sierra tango')
NAPAKA!
>>> razberiNATODeLux('sierra tango alpha romeo - sierra echo mike - 1 8 - lima echo tango .')
star-sem-18-let.
Kronogram je napis, ki ga običajno najdemo na spomenikih, v katerem je zakodirana letnica dogodka, ki ga spomenik obeležuje. Letnico v poenostavljenem kronogramu dobimo tako, da seštejemo vse vrednosti tistih črk, ki lahko nastopajo v rimskih številkah. Vrednosti črk:
• I … 1 • V … 5 • X … 10 • L … 50 • C … 100 • D … 500 • M … 1000
Sestavite funkcijo kronogram(napis), ki za poljuben napis izračuna letnico,
ki se skriva v njem. Letnico izračunajte tako, da pogledate vsako črko in če
je enaka črki iz zgornjega seznama, letnico povečajte za vrednost, ki jo črka
predstavlja.
Dana je funkcija krajse_kronogram(napis), ki za poljuben napis izračuna
letnico, ki se skriva v njem, s pomočjo tabele, v katero zapišemo črke in
njim pripadajoče vrednosti (npr. [("I, 1"), ...]).
Žal pa ima nekaj napak. Odpravi jih!
Naj bosta in niza dolžine , sestavljena iz samih in
(recimo jima binarna niza). Hammingova razdalja med binarnima nizoma in je število pozicij v katerih se razlikujeta.
Sestavite funkcijo hammingova_razdalja(a, b), ki vrne Hammingovo razdaljo
med a in b. Če niza nista enakih dožin, naj funkcija vrne None.
Na primer:
>>> hammingova_razdalja('00100', '10000')
2
>>> hammingova_razdalja('11100', '00011')
5
>>> hammingova_razdalja('11100000', '00011')
None
Recimo, da imamo tri binarne nize , , dolžine . Mediana nizov
, , je binarni niz dolžine , katerega -ta črka je tista črka,
ki predstavlja večino med -timi črkami nizov , , .
Sestavite funkcijo mediana(a, b, c), ki vrne mediano nizov a, b in c.
Na primer:
>>> mediana('0000', '1100', '1010')
'1000'
>>> mediana('10101', '11010','00011')
'10011'
Naj bo tabela različnih binarnih nizov dolžine . Pravimo, da je
tabela medianska, če je za vsako trojico nizov iz tudi njihova mediana
v . Sestavite funkcijo je_medianska(s), ki vrne True, če je tabela s
medianska in False v nasprotnem primeru.
Na primer:
>>> je_medianska(['111','110','100','000'])
True
>>> je_medianska(['010', '100','001'])
False
Recimo, da opazite na majhnem seznamu binarnih nizov, da za poljubno trojico
nizov , , in njihovo mediano velja:
, kjer je Hammingova razdalja
med in . Radi bi imeli program, ki preveri, ali to velja na več
primerih. Sestavite funkcijo ali_velja(s), ki prejme seznam s binarnih
nizov enake dolžine in preveri ali zgornja trditev velja za vsako trojico
nizov iz tega seznama.
Na primer:
>>> ali_velja(['000','001','011', '111'])
True
Za naravno število n dobimo števke na sledeči način: enice so ostanek pri
deljenju števila n z 10, desetice so ostanek pri deljenju celoštevilskega
količnika n//10 z 10, stotice so ostanek pri deljenju celoštevilskega
količnika n//100 z 10 itd. Enaka ideja deluje, če želimo dobiti števke
števila n v kakšnem drugem številskem sestavu. Na primer, pri osnovi 3 so
'enice' ostanek pri deljenju števila n s 3, 'trojice' ostanek pri deljenju
celoštevilskega količnika n//3 s 3, 'devetice' ostanek pri deljenju
celoštevilskega količnika n//9 s 3 itd.
Napišite funkcijo pretvori_iz_desetiskega(n, b), ki v obliki niza vrne
zapis števila n v sestavu z osnovo b. Predpostaviti smete, da je b
naravno število med 2 in 10.
Primer:
>>> pretvori_iz_desetiskega(14, 2)
'1110'
>>> pretvori_iz_desetiskega(14, 7)
'20'
Možne so tudi osnove, večje od 10, le da potrebujemo več števk. Običaj je, da se števke, večje od 9, označujejo z angleškimi velikimi tiskanimi črkami; tako A predstavlja 10, B predstavlja 11 itd. Na primer, šestnajstiški sistem vsebuje števke 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Z običajnimi števkami in črkami skupaj tako dobimo 36 možnih števk.
Napišite funkcijo boljsi_pretvori_iz_desetiskega(n, b), ki deluje za vse
osnove od 2 do 36.
Primer:
>>> boljsi_pretvori_iz_desetiskega(200, 16)
'C8'
Napišite še funkcijo pretvori(n, a, b), kjer n predstavlja zapis
števila v osnovi a, rezultat pa je isto število, zapisano v osnovi b.
Parameter n je lahko dan kot število ali kot niz, rezultat pa naj bo
v vsakem primeru niz. Privzeta vrednost za a in b naj bo 10
(dovoljene so od 2 do 36).
Primer:
>>> pretvori('A1', a=16, b=9)
'188'
>>> pretvori(100, b=8)
'144'
Namig: tu si lahko prebereš nekaj malega o privzetih vrednostih argumentov v pythonu.
Klodovik (papiga) in ne Klodvik (frankofonski kralj)/ bi rad zašifriral svoja besedila, da jih nepoklicane osebe ne bodo mogle prebrati. To stori tako, da najprej v besedilu vse male črke spremeni v velike in odstrani vse znake, ki niso črke. Klodvik vsa pomembna besedila piše v angleščini, zato bomo uporabljali angleško abecedo.
Na primer iz besedila 'Attack at dawn!' dobi besedilo 'ATTACKATDAWN'.
Nato ga zapiše cik-cak v treh vrsticah, kot prikazuje primer:
A...C...D...
.T.A.K.T.A.N
..T...A...W.
Sestavite funkcijo cik_cak(niz), ki vrne trojico nizov (torej tuple) in
sicer prvo, drugo in tretjo vrstico v tem zapisu.
Primer:
>>> cik_cak('Attack at dawn!')
('A...C...D...', '.T.A.K.T.A.N', '..T...A...W.')
Zašifrirano besedilo dobi tako, da najprej prepiše vse znake iz prve vrstice,
nato vse znake iz druge vrstice in na koncu še vse znake iz tretje vrstice. V
zgornjem primeru bi tako dobil 'ACDTAKTANTAW'. Sestavite funkcijo
cik_cak_sifra(niz), ki dobi kot argument niz in vrne zašifrirano besedilo.
Primer:
>>> cik_cak_sifra('Attack at dawn!')
'ACDTAKTANTAW'
Klodovik se zelo razjezi, ko dobi elektronsko pošto v takšni obliki:
Kar sva si obljubljala že leta, si želiva potrditi tudi pred prijatelji in celo
žlahto. Vabiva te na
poročno slovesnost, ki bo
10. maja 2016 ob 15. uri na gradu Otočec. Prijetno druženje bomo
nadaljevali v hotelu Mons. Tjaša in Pavle
Nepopisno mu gre na živce, da je med besedami po več presledkov. Še bolj pa ga nervira, ker so nekatere vrstice precej daljše od drugih. Ker je Klodvik vaš dober prijatelj, mu boste pomagali in napisali funkcije, s katerimi bo lahko olepšal besedila.
Najprej napišite funkcijo razrez(niz), ki kot argument dobi niz in vrne
tabelo besed v tem nizu. Besede so med seboj ločene z enim ali večimi
praznimi znaki: ' ' (presledek), '\t' (tabulator) in '\n' (skok v novo
vrstico). Pri tej nalogi ločilo obravnavamo kot del besede.
Primer:
>>> razrez(' Kakršen\t pastir, \n\ntakšna čreda. ')
['Kakršen', 'pastir,', 'takšna', 'čreda.']
Sedaj, ko že imate funkcijo razrez, bo lažje napisati tisto funckijo, ki
jo Klodovik zares potrebuje. To je funkcija olepsaj_besedilo(niz, sirina),
ki kot argumenta dobi niz in naravno število sirina. Funkcija vrne olepšano
besedilo, kar pomeni naslednje:
sirina znakov (pri čemer znaka
'\n' na koncu vrstice ne štejemo).Predpostavite, da dolžina nobene besede ni več kot sirina in da je niz
neprazen.
Primer:
>>> lepo_besedilo = olepsaj_besedilo(' Jasno in svetlo \t\tna sveti \t\n\nvečer, dobre\t\t letine je dost, če pa je\t oblačno in temno, žita ne bo.', 20)
>>> print(lepo_besedilo)
Jasno in svetlo na
sveti večer, dobre
letine je dost, če
pa je oblačno in
temno, žita ne bo.
V nekem podjetju zbirajo podatke o osebah, ki brskajo po medmrežju. Podatki so shranjeni v slovarjih (en slovar za vsako osebo). Ključ v takem slovarju je lastnost, vrednosti pa podatek o tej lastnosti za določeno osebo. Primeri takšnih slovarjev:
oseba1 = {'ime': 'Božidar', 'telefon': '031918211',
'obiskane spletne strani': ['facebook.com', 'google.com']}
oseba2 = {'ime': 'Pikica', 'naslov': 'Dunajska 105', 'številka noge': 42,
'prijatelji': ['Marko', 'Ana']}
Sestavite funkcijo podatek(oseba, lastnost), ki vrne podatek o
lastnosti lastnost, ki ga imamo v slovarju oseba. Funkcija naj vrne
None, če se ta podatek v slovarju ne nahaja. Primer:
>>> podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'naslov')
'Dunajska 105'
>>> podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'prijatelji')
None
Pri tem ne smeš uporabiti get!
Sestavite funkcijo pridobi_podatek(oseba, lastnost), ki vrne podatek o
lastnosti lastnost, ki ga imamo v slovarju oseba. Funkcija naj vrne
None, če se ta podatek v slovarju ne nahaja. Primer:
>>> pridobi_podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'naslov')
'Dunajska 105'
>>> pridobi_podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'prijatelji')
None
Pri tem si nujno pomagajte z metodo get
Za osebi oseba1 in oseba2 pravimo, da se ujemata v lastnosti
lastnost, če za obe osebi poznamo podatka o tej lastnosti in sta
podatka enaka. Če pa za obe osebi poznamo podatka in sta podatka
različna, pa pravimo, da se osebi razlikujeta v lastnosti lastnost.
Na primer, osebi
oseba1 = {'ime': 'Janez', 'priimek': 'Novak'}
oseba2 = {'ime': 'Jože', 'priimek': 'Novak', 'starost': 20}
se ujemata v lastnosti 'priimek' in razlikujeta v lastnosti 'ime'.
(V lastnosti 'starost' se niti ne ujemata niti ne razlikujeta.)
Sestavite funkcijo ujemanje(oseba1, oseba2), ki pove, v koliko
lastnostih se osebi oseba1 in oseba2 ujemata in v koliko lastnostih
se razlikujeta. Rezultat naj funkcija vrne kot nabor z dvema elementoma.
Primer:
>>> ujemanje({'ime': 'Janez', 'priimek': 'Novak'},
{'ime': 'Jože', 'priimek': 'Novak', 'starost': 20})
(1, 1)
Dva različna slovarja oseba1 in oseba2 lahko predstavljata isto
osebo. To se zgodi, če se slovarja ne razlikujeta v več kot 1 lastnosti
in se ujemata vsaj v 3 lastnostih ali če sta v obeh slovarjih lastnosti
ime in priimek enaki. Na primer, slovarja
oseba1 = {'ime': 'Janez', 'priimek': 'Novak', 'telefon': '031123234',
'starost': 90}
oseba2 = {'ime': 'Janez', 'priimek': 'Novak', 'davčna': '43424140'}
predstavljata isto osebo, prav tako slovarja
oseba1 = {'ime': 'Janez', 'priimek': 'Novak', 'telefon': '031123234',
'starost': 90, davčna': '43424140'}
oseba2 = {'ime': 'Luka', 'priimek': 'Novak', 'starost': 90,
'davčna': '43424140', 'telefon': '031123234'}
Sestavite funkcijo ista(oseba1, oseba2), ki preveri, ali slovarja
predstavljata isto osebo. Na primer, za zgornja primera mora funkcija
vrniti True.
V seznamu slovarjev, ki predstavljajo osebe, se lahko zgodi, da več slovarjev predstavlja isto osebo (isto v smislu prejšnje podnaloge). V takem primeru pravimo, da so ti slovarji podvojeni.
Sestavite funkcijo podvojeni(seznam_oseb), ki vrne seznam vseh podvojenih
slovarjev iz seznama seznam_oseb. Slovarji naj bodo razvrščeni v istem vrstnem
redu kot v seznamu seznam_oseb. Primer:
>>> podvojeni([{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 19'},
{'ime': 'Žan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Žan', 'priimek': 'Noč', 'naslov': 'Jamova 25'}])
[{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 19'}]
Babica Metka in njen vnuk Boštjan sta se odločila, da si bosta pošiljala skrivna sporočilca zakodirana s substitucijsko šifro.
Substitucijska šifra je enostaven način šifriranja, pri katerem vsako črko iz dane abecede zamenjamo z neko drugo črko. Tako šifro predstavimo s slovarjem, ki ima za ključe vse črke iz abecede, pripadajoče vrednosti pa so črke, s katerimi jih zašifriramo.
Tako slovar {'A': 'B', 'C': 'C', 'B': 'D', 'D': 'A'} pove, da se
'A' zašifrira v 'B', 'B' v 'D', 'D' v 'A', 'C' pa se ne spremeni.
Sestavite funkcijo sifriraj(sifra, beseda), ki vrne besedo, zašifrirano
z dano šifro. Predpostavite lahko, da vse črke v besedi nastopajo v
šifri. Zgled:
>>> sifriraj(nasa_sifra, "IGRICA")
'BPLBZO'
Sestavite funkcijo je_sifra(slovar), ki ugotovi, ali slovar predstavlja
šifro, torej ali je bijekcija črk na neki abecedi (bijektivna
preslikava abecede samo vase). Zgled:
>>> je_sifra(nasa_sifra)
True
Namig: pri bijektivni preslikavi je poljuben element iz množice B slika točno enega elementa množice A.
Sestavite funkcijo inverz(sifra), ki vrne inverz dane šifre, če ta
obstaja. V nasprotnem primeru funkcija vrne None. Zgled:
>>> inverz({'A': 'D', 'B': 'A', 'D': 'J', 'J': 'B'})
{'A': 'B', 'B': 'J', 'J': 'D', 'D': 'A'}
Namig: inverz obstaja samo kadar je slovar, ki predstavlja šifro, bijekcija črk na neki abecedi.
Sestavite funkcijo odsifriraj(sifra, beseda), ki sprejme šifro in
zašifrirano besedilo, vrne pa odšifrirano besedilo. Če slovar
ni bijekcija (in se torej besedilo ne da nujno odšifrirati), naj
funkcija vrne None. Zgled:
>>> odsifriraj(nasa_sifra, 'BPLBZO')
'IGRICA'
Babica Metka bi rada svojemu vnuku Boštjanu zelo rada pomagala do boljše ocene pri matematiki. Ker trenutno pri pouku obravnavajo permutacije, o katerih sama ne ve prav dosti, ji priskočite na pomoč.
Permutacijo naravnih števil od do lahko predstavimo s slovarjem.
Na primer permutacijo, ki slika v , v , število pa
pusti pri miru, predstavimo s slovarjem {1: 3, 2: 2, 3: 1}.
Sestavite funkcijo slika(permutacija, x), ki kot argumenta dobi slovar
permutacija, ki predstavlja permutacijo, in število x. Funkcija naj
vrne sliko števila x s podano permutacijo. Zgled:
>>> slika({1: 3, 2: 4, 3: 2, 4: 1}, 4)
1
Sestavite funkcijo je_permutacija(slovar), ki vrne True, če dan
slovar predstavlja permutacijo, in False sicer. Zgled:
>>> je_permutacija({1: 3, 2: 5, 5: 1})
False
Sestavite funkcijo slike(permutacija, x, n), ki vrne zaporedje slik,
ki ga dobimo, če začnemo s številom x in na njem n-krat uporabimo
permutacijo permutacija. Zgled:
>>> slike({1: 3, 2: 4, 3: 2, 4: 1}, 1, 2)
[1, 3, 2]
Pri nas trenutno obstajajo tri davčne stopnje: višja, nižja in oproščena. Davčne stopnje so podane v slovarju, kjer so ključi vedno taki, kot prikazuje zgled davcne_stopnje = {'V': 22, 'N': 9.5, 'O': 0}
Lastnik popularne trgovinice (ki ima celo lastno pekarno), vas je najel, da mu napišete program za sestavljanje računov.
Nakupi so shranjeni v slovarju kosarice, katerega ključi so imena kupcev,
vrednosti pa slovarji predmetov in količin. Zgled:
kosarice = {'Janez': {'banana': 5, 'jogurt': 7},
'Mojca': {'francoska štrucka': 7}}
V tej trgovinici so francoske štručke zelo popularne. Vsak kupec vedno
kupi vsaj dve, tudi če tega nima zapisanega na nakupovalnem listku.
Sestavite funkcijo dodaj_strucke(kosarice), ki sestavi in vrne nov slovar,
v katerem ima vsak kupec poleg vsega, kar že ima, še vsaj po dve francoski
štručki. Zgled:
>>> kosarice = {'Janez': {'banana': 5, 'jogurt': 7}, 'Mojca': {'francoska štručka': 7}}
>>> dodaj_strucke(kosarice)
{'Janez': {'jogurt': 7, 'francoska štručka': 2, 'banana': 5},
'Mojca': {'francoska štručka': 7}}
Šef trgovine je pripravil cenik vseh izdelkov, ki jih trgovinica
prodaja. Vsak izdelek ima par podatkov in sicer bruto ceno in davčno
stopnjo. Napišite funkcijo neto_in_davek(cenik, davcne_stopnje), ki sestavi
in vrne nov slovar, v katerem bo par podatkov in sicer: neto cena izdelka in
davek, ki ga mora trgovinica plačati državi, če so trenutno veljavne podane
davčne stopnje. Pri tem vse cene in davke zaokroži na 5 decimalnih mest.
Zgled:
>>> cenik = {'voda': (0.25, 'N'), 'sok': (1.20, 'V'), 'znamka A': (0.23, 'O')}
>>> neto_in_davek(cenik, {'V': 20, 'N': 8.5, 'O': 0})
{'sok': (1.0, 0.2), 'voda': (0.23041, 0.01959), 'znamka A': (0.23, 0.0)}
Sestavite funkcijo cene_z_ddv(kosarice, cenik, davcne_stopnje), ki dobi
slovar nakupov in cenik (v originalni obliki), ter sestavi nov slovar nakupov,
ki za vsak nakup vsebuje peterico:
(kolicina, neto_na_enoto, neto_skupaj, davcna_stopnja, davek_skupaj)
(Ne pozabite upoštevati, da vsak kupi vsaj dve štručki.)
Pri tem vse cene in davke zaokroži na 5 decimalnih mest. Zgled:
>>> cenik = {'voda': (0.25, 'N'), 'sok': (1.25, 'V'), 'znamka A': (0.23, 'O'),
'francoska štručka': (1, 'N')}
>>> kosarice = {'Janez': {'voda': 5, 'sok': 7},
'Mojca': {'francoska štručka': 7}}
>>> davcne_stopnje = {'V': 20, 'N': 8.5, 'O': 0}
>>> cene_z_ddv(kosarice, cenik, davcne_stopnje)
{'Janez': {'voda': (5, 0.23041, 1.15205, 'N', 0.09795),
'sok': (7, 1.04167, 7.29169, 'V', 1.45831),
'francoska štručka': (2, 0.92166, 1.84332, 'N', 0.15668)},
'Mojca': {'francoska štručka': (7, 0.92166, 6.45162, 'N', 0.54838)}}
V nalogi se bomo igrali s slovarji, ki opisujejo, kje se nahaja kakšen kraj. Slovar je lahko recimo, tak
svet = {
"Evropa": {
"Slovenija": {
"Gorenjska": {
"Kranj": {},
"Radovljica": {},
"Zali log": {},
},
"Štajerska": {
"Maribor": {},
"Celje": {}
},
"Osrednja": {
"Ljubljana": {
"Vič": {
"FMF": {
"2.02": {
"tretja vrsta desno": {
"peti stol z desne": {
"Benjamin": {}
}
}
}
}
},
"Šiška": {}
}
}
},
"Nemčija": {
"Bavarska": {
"Munchen": {}
},
"Berlin": {}
},
},
"Amerika": {
"ZDA": {
"Teksas": {
"Houston": {},
"Austin": {}
},
"Kalifornija": {
"San Francisco": {}
},
"Anchorage": {}
},
"Kanada": {}
},
"Azija": {
"Osaka": {}
}
}
Ključi slovarja so torej opisi, vsebine pa so slovarji, ki so lahko tudi prazni. Namig: Oglejte si kako preveriti, ali je neka struktura prazna,
Napiši funkcijo vrni_vse(slovar_opisov), ki kot argument dobi slovar,
kakršen je gornji, in vrne po abecedi urejeno tabelo vseh opisov
v njem.
Primer:
>>> prvo_nadstropje = {"Prvo nadstropje": {"soba": {"računalnik": {}, "jaz": {}},
"otroška soba": {"Martin": {"ostali piškoti": {}}}}}
>>> vrni_vse(prvo_nadstropje)
['Martin', 'Prvo nadstropje', 'jaz', 'ostali piškoti', 'otroška soba', 'računalnik', 'soba']
Napiši funkcijo prestej(slovar_opisov), ki vrne število vseh opisov,
ki se pojavijo v podanem slovarju.
Primer:
>>> prvo_nadstropje = {"Prvo nadstropje": {"soba": {"računalnik": {}, "jaz": {}},
"otroška soba": {"Martin": {"ostali piškoti": {}}}}}
>>> prestej(prvo_nadstropje)
7
Denimo, da imamo slovar (kot sta kraji in svet), ki kot vrednosti spet
vsebuje slovarje.
Sestavi funkcijo naj_slovar(slovar), ki vrne tisti slovar,
ki vsebuje največ ključev.
Predpostaviš lahko, da je samo en tak slovar (torej ima le en slovar to največje število ključev.
Primer:
>>> prvo_nadstropje = {"Prvo nadstropje": {
"soba": {"računalnik": {}, "jaz": {}, "miza": {}, "tipkovnica": {}},
"otroška soba": {"Martin": {"ostali piškoti": {}}},
"kopalnica": {"milo": {}}}}
>>> naj_slovar(prvo_nadstropje)
{'računalnik': {}, 'jaz': {}, 'miza': {}, 'tipkovnica': {}}
Sestavi funkcijo je_v_slovarju(slovar, nekaj), ki ugotovi, ali je
v slovarju slovar tudi niz nekaj (bodisi kot ključ, bodisi v
vrednosti, ki je spet slovar).
Primer:
>>> prvo_nadstropje = {"Prvo nadstropje": {"soba": {"računalnik": {}, "jaz": {}},
"otroška soba": {"Martin": {"ostali piškoti": {}}}}}
>>> je_v_slovarju(prvo_nadstropje, "računalnik")
True
>>> je_v_slovarju(prvo_nadstropje, "Martin")
True
>>> je_v_slovarju(prvo_nadstropje, "kremna rezina")
False
Sestavi funkcijo vrni_vrednost(slovar, nekaj), ki vrne tisto vrednost
iz slovarja slovarjev slovar, ki pripada ključu nekaj
Če pa v slovarju slovarjev nekaj ni ključ, naj vrne None.
Primer:
>>> prvo_nadstropje = {"Prvo nadstropje": {"soba": {"računalnik": {}, "jaz": {}},
"otroška soba": {"Martin": {"ostali piškoti": {}}}}}
>>> vrni_vrednost(prvo_nadstropje, "Martin")
{"ostali piškoti": {}}
>>> vrni_vrednost(prvo_nadstropje, "jaz")
{}
>>> vrni_vrednost(prvo_nadstropje, "kopalnica")
None
V nekem uspešnem podjetju ima skoraj vsak zaposleni svojega šefa. Seveda imajo tudi šefi svoje šefe in ti spet svoje šefe itn. Dobili smo podatke o hierarhiji v podjetju in ugotovili, da velja naslednje:
Napisali bomo nekaj funkcij, s katerimi bomo preučili razmere v podjetju.
Podatke smo dobili v obliki tabele parov oblike (uslužbenec, šef).
Vsi uslužbenci so predstavljeni z nizi (ki so običajno njihova imena oz.
priimki). Zgled:
[('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')]
Komentar: Tilen ima pod seboj dva podrejena (Andreja in Mojco), njegovi šef pa je Zoran. Zoran nima šefa, vsi ostali pa so njegovi podrejeni.
Napišite funkcijo slovar_sefov(tabela), ki bo iz zgoraj opisane
tabele zgradila slovar šefov. Ključi v slovarju naj bodo uslužbenci,
vrednosti pa njihovi šefi. Zgled:
>>> slovar_sefov([('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')])
{'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'}
Napišite funkcijo neposredno_podrejeni(tabela), ki bo iz zgoraj opisane
tabele sestavila slovar neposredno podrejenih. Vrednost pri vsakem
ključu naj bo množica tistih uslužbencev, ki imajo le-ta ključ za svojega
šefa. Zgled:
>>> neposredno_podrejeni([('Mojca', 'Tilen'), ('Andrej', 'Tilen'), ('Tilen', 'Zoran')])
{'Zoran': {'Tilen'}, 'Tilen': {'Andrej', 'Mojca'}}
Zoranu je torej neposredno podrejen le Tilen, Tilnu pa sta podrejena tako Andrej kot Mojca.
Sestavite funkcijo veriga_nadrejenih(usluzbenec, slovar), ki kot prvi
argument dobi niz, ki predstavlja nekega uslužbenca, kot drugi argument
pa dobi slovar šefov (v obliki kot ga vrne funkcija slovar_sefov).
Funkcija naj sestavi tabelo, ki po vrsti vsebuje: šefa osebe usluzbenec,
šefa od njegovega šefa itn. (dokler končno ne pridemo do osebe, ki nima šefa).
Zgled:
>>> veriga_nadrejenih('Mojca', {'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'})
['Tilen', 'Zoran']
Mojci je nadrejen Tilen, kateremu je nadrejen Zoran, torej sta Mojčina šefa Tilen in Zoran.
Sestavite funkcijo mnozica_podrejenih(usluzbenec, slovar), ki kot prvi
argument dobi ime uslužbenca, kot drugi argument pa slovar neposredno
podrejenih (v obliki kot ga vrne funkcija neposredno_podrejeni). Funkcija
naj sestavi in vrne množico vseh tistih oseb, ki so (posredno ali
neposredno) podrejeni osebi usluzbenec. Zgled:
>>> mnozica_podrejenih('Zoran', {'Zoran': {'Tilen'}, 'Tilen': {'Andrej', 'Mojca'}, 'Mojca' : {'Urša'}})
{'Andrej', 'Mojca', 'Tilen', 'Urša'}
Zoranju je neposredno podrejen Tilen, torej sta mu podrejena tudi Tilnova podrejena Andrej in Mojca, ter Urša, ker je ta podrejena Mojci.
Tistemu uslužbencu, za katerega velja:
pravimo big boss. Sestavite funkcijo big_boss(slovar), ki kot argument
dobi slovar nadrejenih in vrne ime osebe, ki je big boss v podjetju oz.
vrednost None, če to podjetje nima big boss-a. Zgled:
>>> big_boss({'Andrej': 'Tilen', 'Mojca': 'Tilen', 'Tilen': 'Zoran'})
'Zoran'
Se še spomnimo Metke in Boštjana in permutacij? Če ne, poišči nalogo Permutacije - lažje, saj bomo pri reševanju uporabili tudi tam razvite funkcije.
Samo da se spomnimo:
Permutacijo naravnih števil od do lahko predstavimo s slovarjem.
Na primer permutacijo, ki slika v , v , število pa
pusti pri miru, predstavimo s slovarjem {1: 3, 2: 2, 3: 1}.
Sestavite funkcijo cikel(permutacija, x), ki vrne celoten cikel, ki
se začne s številom x. Zgled:
>>> cikel({1: 3, 2: 2, 3: 1}, 1)
[1, 3]
>>> cikel({1: 3, 2: 2, 3: 1}, 2)
[2]
Sestavite funkcijo cikli(permutacija), ki vrne seznam disjunktnih
ciklov dane permutacije. Vsak cikel naj se začne z najmanjšim številom
v ciklu, cikli pa naj bodo urejeni po začetnem številu. Zgled:
>>> cikli({1: 3, 2: 5, 3: 1, 4: 2, 5: 4})
[[1, 3], [2, 5, 4]]
>>> cikli({1: 6, 2: 5, 3: 3, 4: 2, 5: 4, 6: 1})
[[1, 6], [2, 5, 4], [3]]
Upravljalec restavracije te prosi za pomoč. Ljudje so ozaveščeni in skrbi jih gensko spremenjena hrana. Moram mu pomagati, da bo izračunal količino GSOja, ki bo zapisana v novem jedilniku.
Kuhar je že sestavil slovar vseh jedi na jedilniku skupaj z njihovimi
sestavinami. Sestavine so tudi podane v obliki slovarja z vnosi
oblike sestavina: količina. Enota pri količini ni podadana (lahko je to
teža, volumen, število kosov, …). Ker se je zelo mudilo, je pri jedeh,
kjer je cela jed ena sama sestavina, pisal le prazno množico. Sestavite
funkcijo odpravi_okrajsave(recepti), ki sestavi in vrne nov slovar,
ki ne vsebuje okrajšav. Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30}, 'solata': dict()}
>>> odpravi_okrajsave(recepti)
{'solata': {'solata': 1}, 'pica': {'sir': 30, 'moka': 80}}
V tistih množicah, ki predstavljajo recepte, je kuhar količine sestavin
podal v gramih. Da bomo lažje računali GSO, jih je treba "normalizirat",
da bo vse v procentih. Napišite funkcijo normaliziraj_kolicine(recepti),
ki kot argument dobi slovar receptov in vrne "normaliziran" slovar receptov
(tj. vsota vseh količin v vsakem receptu naj bo točno 100). Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30} 'solata': dict()}
>>> normaliziraj_kolicine(recepti)
{'solata': {'solata': 100.0},
'pica': {'sir': 27.272727272727273, 'moka': 72.72727272727273}}
Upravljalec restavracije vam je priskrbel še seznam vseh elementarnih
sestavin skupaj z njihovim deležem GSO. Sestavite funkcijo
delez_gso(recepti, elementarne), ki dobi slovar z recepti in slovar
z deleži GSO v elementarnih sestavinah in poračuna deleže GSO v jedeh.
V slovarju elementarnih sestavin so vsaj vse elementarne sestavine, ki
se nahajajo v receptih, lahko pa jih je tudi več. Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30}, 'solata': dict()}
>>> elementarne = {'moka': 70, 'sir': 10, 'solata': 0}
>>> delez_gso(recepti, elementarne)
{'solata': 0.0, 'pica': 53.63636363636364}
Poleg običajnega imajo v restavraciji tudi specialni jedilnik, ki vsebuje
eksotične jedi. Te vsebujejo tudi sestavine, ki prihajajo iz "sumljivih"
dežel in deleža GSO ni mogoče ugotoviti. Napišite še funkcijo
delez_gso_special(recepti, elementarne), ki je podobna kot v prejšni
nalogi, le da vsaki jedi priredi "interval" (tj. par (min_gso, max_gso)).
V minimalnem primeru predpostavimo povsod 0 % GSO, v maximalnem primeru
pa povsod 100 % GSO. Zgled:
>>> recepti = {'pica_special': {'moka': 80, 'sir': 30, 'namaz': 10}, 'solata_special': dict()}
>>> elementarne = {'moka': 70, 'sir': 10, 'solata': 5}
>>> delez_gso_special(recepti, elementarne)
{'pica_special': (49.16666666666667, 57.5), 'solata_special': (0.0, 100.0)}
Kadar nas zanima, kam se lahko iz danega kraja odpravimo, lahko odpremo zemljevid in pogledamo, v katere kraje nas iz danega kraja vodijo ceste. Recimo iz Celja se lahko odpravimo proti Velenju, Laškem ali Rogaški Slatini, iz Logatca se lahko odpravimo proti Idriji, Postojni in Vrhniki, iz Vrhinike se lahko odpravimo nazaj proti Logatcu ali proti Ljubljani.
Tak zemljevid lahko predstavimo tudi z usmerjenim grafom. Usmerjen graf sestavljata množica vozlišč in množica usmerjenih povezav . Vsaki usmerjeni povezavi pripada vozlišče, ki ga imenujemo začetek povezave, in vozlišče, ki ga imenujemo konec povezave.
Običajno si vozlišča predstavljamo kot točke v ravnini, povezave pa kot puščice med njimi. Puščica je usmerjena od začetnega proti končnemu vozlišču.
Usmerjene grafe lahko predstavimo na več načinov. Lahko ga podamo kot množico vozlišč in seznam parov usmerjenih povezav:
V = {'Logatec', 'Vrhnika', 'Ljubljana', 'Postojna', 'Idrija'}
A = [('Logatec', 'Vrhnika'), ('Logatec', 'Postojna'), ('Logatec', 'Idrija'), ('Vrhnika', 'Logatec'), ('Vrhnika', 'Ljubljana')]
Lahko pa ga podamo v obliki slovarja naslednikov:
{'Logatec': ['Vrhnika', 'Postojna', 'Idrija'], 'Vrhnika': ['Logatec', 'Ljubljana']}
(V zgornjem primeru smo predpostavili, da se iz Postojne, Idrije in Ljubljane, ne da priti nikamor (kar seveda ni res))
Ključi v tem slovarju so vozlišča, vrednost pri posameznem ključu u pa
je seznam vseh vozlišč, ki so nasledniki vozlišča u. (Vozlišče je
naslednik vozlišča , če v digrafu obstaja usmerjena povezava .)
V nadaljevanju predpostavite, da grafi ne bodo imeli izoliranih vozlišč (to so vozlišča, ki niso niti začetek niti konec katere od povezav).
Napišite funkcijo slovar_naslednikov(seznam_povezav), ki kot argument
dobi seznam povezav digrafa, sestavi in vrne pa naj pripadajoči slovar
naslednikov. Zgled:
>>> slovar_naslednikov([('a', 'b'), ('c', 'b'), ('c', 'd'), ('d', 'a'), ('a', 'c')])
{'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']}
Seznami naslednikov naj bodo urejeni.
Sestavite funkcijo seznam_povezav(digraf), ki kot argument dobi
usmerjen graf, ki je podan kot slovar naslednikov. Funkcija naj sestavi
in vrne seznam usmerjenih povezav. (Torej, funkcija seznam_povezav naj
naredi ravno obratno kot funkcija slovar_naslednikov.) Zgled:
>>> seznam_povezav({'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']})
[('a', 'b'), ('a', 'c'), ('c', 'b'), ('c', 'd'), ('d', 'a')]
Seznam povezav, ki ga vrne funkcija, naj bo urejen.
Napišite funkcijo nasprotni_graf(digraf), ki dobi usmerjen graf
v obliki slovarja naslednikov, sestavi in vrne pa naj nasprotni graf
(tudi v obliki slovarja naslednikov). Nasprotni graf grafa ima enako
množico vozlišč kot , povezave pa imajo obrnjeno smer. Zgled:
>>> nasprotni_graf({'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']})
{'a': ['d'], 'c': ['a'], 'b': ['a', 'c'], 'd': ['c']}
Seznami naslednikov naj bodo urejeni.
Usmerjene grafe lahko sestavimo iz večih usmerjenih podgrafov. Vsak posamezen podgraf je predstavljen s slovarjem, za katerega velja, da ima vsako vozlišče le enega naslednika.
Sestavite funkcijo sestavljen_graf(tabela_podgrafov), ki bo iz
dane tabele usmerjenih podgrafov sestavila slovar, ki bo predstavljal
graf v obliki slovarja naslednjikov. Vrednosti naj bodo v
tabelah zapisane v enakem vrstnem redu, kot nastopajo v tabeli podgrafov.
Zgled:
>>> sestavljen_graf([{'a': 'b', 'c': 'b'}, {'a': 'c', 'c': 'd', 'd': 'a'}])
{'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']}
Spet se bomo ukvarjali z rodovniki (Celjskih grofov in drugih). Rodovnik imamo podan kot slovar, kjer je ključ ime "glave rodbine" vrednost pa tabela imen otrok. Recimo:
rodovnik =
{'Ulrik I.': ['Viljem'], 'Margareta': [], 'Herman I.': ['Herman II.', 'Hans'],
'Elizabeta II.': [], 'Viljem': ['Ana Poljska'], 'Elizabeta I.': [],
'Ana Poljska': [], 'Herman III.': ['Margareta'], 'Ana Ortenburška': [],
'Barbara': [], 'Herman IV.': [], 'Katarina': [], 'Friderik III.': [],
'Herman II.': ['Ludvik', 'Friderik II.', 'Herman III.', 'Elizabeta I.', 'Barbara'],
'Ulrik II.': ['Herman IV.', 'Jurij', 'Elizabeta II.'], 'Hans': [], 'Ludvik': [],
'Friderik I.': ['Ulrik I.', 'Katarina', 'Herman I.', 'Ana Ortenburška'],
'Friderik II.': ['Friderik III.', 'Ulrik II.'], 'Jurij': []}
rodovnik['Friderik II.']
nam torej vrne
['Friderik III.', 'Ulrik II.']
Je v rodbini?
Sestavi funkcijo je_v_rodbini(ime, glava_rodbine, rodovnik), ki ugotovi, ali
je oseba z imenom ime v rodbini osebe glava_rodbine. Funkcija torej
vrne True oz. False.
Kdo se podpisuje najdlje časa?
Sestavi funkcijo najdaljsi_podpis(glava_rodbine, rodovnik), ki ugotovi, kdo
v rodbini osebe glava_rodbine ima najdaljše ime za podpis (torej kompletno
ime).
Kdo ima najkrajše ime?
Sestavi funkcijo najkrajse_ime(glava_rodbine, rodovnik), ki ugotovi, kdo
v rodbini osebe glava_rodbine ima najkrajše ime.
(šteje samo krstno ime, brez "Ortenburga" in "Celja" ter brez številk)?
"Ana X" ima torej krajše ime kot "Hugo".
Globina rodbine
"Globino" rodbine definiramo tako: če nekdo nima otrok, je globina njegove rodbine 1. Če ima otroka, ta pa nima vnukov (ali celo več otrok, ti pa nimajo vnukov), je globina rodbine 2. Če nekdo ima vnuke, vendar nobenega pravnuka, je globina njegove rodbine 3.
Sestavi funkcijo globina(glava_rodbine, rodovnik), ki vrne globino rodbine
osebe glava_rodbine v rodovniku rodovnik
Takrat, ko je upokojenki Tini dolgčas, vzame svoji dve posodici z belimi
in rdečimi kroglicami ter začne nizati ogrlice. Te ogrlice bomo predstavili
z nizi, sestavljenimi iz znakov B in R.
Na primer: 'BBRBBRB' in 'RRBBBBB' sta dve izmed 21 možnih ogrlic,
sestavljenih iz petih belih in dveh rdečih kroglic.
Sestavite funkcijo je_ogrlica(niz, b, r), ki preveri, ali niz
predstavlja ogrlico iz b belih in r rdečih kroglic. Na primer:
>>> je_ogrlica('BBRBBRB', 5, 2)
True
>>> je_ogrlica('RRBBBBB', 5, 2)
True
>>> je_ogrlica('BBRBBRB', 2, 5)
False
>>> je_ogrlica('BBRBBRBBB', 5, 2)
False
>>> je_ogrlica('BBRBBRBXY', 5, 2)
False
Z označimo število različnih ogrlic, sestavljenih iz natanko
belih in rdečih kroglic. Če je eno od števil ali enako
nič, potem je . Na primer, , saj iz petih
belih kroglic lahko sestavimo le ogrlico 'BBBBB'.
V nasprotnem primeru pa velja , saj se vsaka izmed ogrlic iz belih in rdečih kroglic:
Sestavite funkcijo stevilo_ogrlic(b, r), ki izračuna število vseh
možnih ogrlic, sestavljenih iz natanko b belih in r rdečih kroglic.
Na primer:
>>> stevilo_ogrlic(5, 0)
1
>>> stevilo_ogrlic(5, 2)
21
>>> stevilo_ogrlic(4, 2)
15
>>> stevilo_ogrlic(5, 1)
6
Sestavite funkcijo ogrlice(b, r), ki generira vse nize,
ki predstavljajo ogrlice, sestavljene iz b belih in r rdečih kroglic.
Funkcija naj nize vrača v abecednem vrstnem redu.
Primer:
>>> ogrlice(2, 2)
['BBRR', 'BRBR', 'BRRB', 'RBBR', 'RBRB', 'RRBB']
Letala letalske družbe SLED pogosto opravljajo precej dolge polete z vmesnimi postanki. V kontroli ob vsakem postanku preverijo, ali bodo letala lahko prispela do cilja s trenutno količino goriva.
Sestavite funkcijo dovolj_goriva(gorivo, pot), kjer je gorivo količina
goriva v letalu na začetku potovanja, pot pa je tabela s potrebnimi
količinami goriva do naslednjega letališča. Funkcija naj vrne True, če je
goriva dovolj za celo pot in False, če bo letalu goriva na poti zmanjkalo.
Če je v letalu ravno prav goriva, naj funkcija vrne True.
>>> dovolj_goriva(200, [25, 60, 43, 28])
True
>>> dovolj_goriva(10, [30, 40])
False
Najprej rešite nalogo z uporabo zanke for ali while.
Sestavite enako funkcijo, (poimenujte jo dovolj_goriva_rek(gorivo, pot)) le
da tokrat ne smete uporabiti zanke for ali while,
pač pa rekurzivni klic.
Pri tej nalogi dobite dva ustavitvena pogoja - enega, če zmanjka goriva in drugega, če ga je dovolj.
Že pri prejšnjih nalogah smo spoznali SSCŠ. Ponovimo še enkrat - seznam seznamov celih števil (SSCŠ) je seznam, katerega elementi so bodisi cela števila bodisi seznami seznamov celih števil. Da bo enostavneje, recimo, da je tudi prazen seznam SSCŠ. Nekaj primerov:
[-1, 2, -3]
[1, [2], 3, [2, 3, 4]]
[[[[0]], 1], [2, [[-3], [4]]]]
Sestavi funkcijo loci_stevila(sscs), ki vrne trojico (poz, nic, neg), ki
pove, koliko je v sscs pozitivnih, ničelnih in koliko negativnih celih števil.
Za primere od zgoraj so rezultati:
(1, 0, 2)
(6, 0, 0)
(3, 1, 1)
Predpostavi, da je parameter zagotovo SSCS.
Sestavi funkcijo je_sscs(sscs), ki preveri (vrne True oz. False), če je dan
seznam res seznam seznamov celih števil.
POZOR: Python pravi, da je isinstance(True, int) enako True, pa tudi
isinstance(False, int) enako True, zato se "znebi" napačnih logičnih
vrednosti z isinstance(True, bool)
Lahko pa uporabiš tudi type(nekaj) is int, ki pa deluje "prav" tudi, če je v x logična vrednost
Sestavi funkcijo koliko_napacnih(sscs), ki prešteje, koliko je v seznamu
seznamov celih števil napačnih podatkov, torej elementov, ki
niso ne cela števila, ne SSCŠ. Če argument ni seznam, vrni None
>>>koliko_napacnih([1, 'bla', 2])
1
>>>koliko_napacnih([True, 2, False])
2
>>>koliko_napacnih([1, [['bla', 'blu'], False], 2])
1
>>>koliko_napacnih([[1.8], [2, 3, [4]], [False, 4, [True]]])
2
>>>koliko_napacnih(12)
None
>>>koliko_napacnih(set())
None
Rekurzija se lahko pojavi tudi brez "eksplicitnega" ustavitvenega pogoja. Npr. takrat, ko je rekurzivni klic del zanke in se lahko zgodi, da so podatki taki, da se zanka ne izvede nikoli.
V podjetju SLED vodijo evidenco svojih zaposlenih tako, da se vedno ve, kdo je
glavni. Za vsakega zaposlenega v tabelo zaposleni vpišejo vse njegove
neposredno podrejene. Če bi imeli štiri zaposlene, kjer bi bil Janez šef,
Liza in Katja njegovi podrejeni, poleg tega pa bi Luka bil podrejen Lizi,
bi tabela zaposleni izgledala tako:
[('Janez', 'Liza'),('Janez', 'Katja'), ('Liza', 'Luka')]
Vsak zaposleni je podrejen kvečjemu eni osebi.
Uredite vrstice kode spodaj, da bo funkcija podrejeni(ime, zaposleni), ki
sprejme ime delavca ime in tabelo zaposleni
in vrne število vseh podrejenih (tudi posredno podrejenih) delavcu z imenom ime,
delovala pravilno.
Poleg tega ima ena vrstica napako, ena pa je odveč.
"""Prešteje uslužbence, podrejene delavcu ime."""
return podrejenih
podrejenih = 0
if sef == ime:
def podrejeni(ime, zaposleni):
for (sef, usluzbenec) in zaposleni:
podrejenih = podrejeni(usluzbenec, zaposleni)
return 0
Sestavite še funkcijo glavni(zaposleni), ki vrne množico vseh glavnih šefov.
Glavni šef je tisti, ki nima nobenega nadrejenega.
Naloga je rešljiva s pomočjo rekurzije, vendar je precej težka, tako da lahko rešite tudi brez rekurzije, oglejte pa si uradno rešitev z rekurzijo, tam se boste še kaj novega naučili.
Pravimo, da je sprehod po točkah v ravnini cik-cakast, če gremo iz točke vedno v točko ali pa v . Torej, na vsakem koraku gremo za eno polje v desno ter bodisi navzdol, bodisi navzgor.
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
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)]
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.
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:
Collatzovo zaporedje tvorimo na sledeč način. Začnemo z nekim naravnim številom , ki ga nato delimo z , če je sodo, ali pa pomnožimo s in prištejemo , če je liho. Postopek ponavljamo, dokler ne pridemo do števila (v tem primeru stvar ni več zanimiva, saj se začno ponavljati števila ). Primer zaporedja, ki se začne s je tako .
Collatzova domneva, ki trdi, da za poljubno naravno število njegovo zaporedje sčasoma doseže , je še vedno nerešena. Ker pa so to (do l. 2017) eksperimentalno preverili za vsa naravna števila med in , se ne bomo bali, da se naše zaporedja ne bodo iztekla v 1.
Vse naloge, razen prve, rešite z rekurzijo!
Sestavite funkcijo naslednji_clen(n), ki izračuna člen, ki v Collatzovemu
zaporedju sledi številu n.
Sestavite funkcijo dolzina_zaporedja(n), ki izračuna dolžino Collatzovega
zaporedja, ki se začne s številom n. Dolžina zaporedja je število korakov,
preden zaporedje doseže 1.
Na primer, dolžina zaporedj, ki se začne s , je tako 8, saj do 1 pridemo v 8 korakih: .
Pozor: Če funkciji podamo argument n = 1, naj vrne 3, saj enico prvič dosežemo po 3 korakih: .
Primeri:
>>> dolzina_zaporedja(2)
1
>>> dolzina_zaporedja(6)
8
>>> dolzina_zaporedja(5)
5
>>> dolzina_zaporedja(1)
3
Sestavite funkcijo najvecji_clen(n), ki izračuna največji člen v
Collatzovem zaporedju, ki se začne s številom n.
V zaporedju, ki se začne s , je največji člen 16: .
Primeri:
>>> najvecji_clen(2):
2
>>> najvecji_clen(6)
16
>>> najvecji_clen(5)
16
>>> najvecji_clen(1)
4
Sestavite funkcijo najdaljse_zaporedje(m, n), ki vrne dolžino najdaljšega
zaporedja med vsemi tistimi Collatzovimi zaporedji, ki se začnejo s števili
med (vključno) m in n.
Primera:
>>> najdaljse_zaporedje(5, 5)
5
>>> najdaljse_zaporedje(5, 8)
16
===============================================================
Sklop nalog, kjer pišemo funkcije, ki naredijo določena opravila z datotekami na nivoju operacijskega sistema. V nalogah bodo potrebne te funkcije:
os.listdir(mapa) seznam datotek in map v mapios.path.isfile(dat) ali je dat »navadna« datotekaos.path.isdir(dat) ali je dat imenikos.path.getsize(dat) velikost datotekeos.path.split(dat) razdeli ime datotekeos.path.getmtime(dat) čas zadnje spremembe datotekeos.rmdir(pot) odstrani mapoos.path.join(mapa1, mapa2, ime_datoteke) združi argumente v veljavno pot - zadnji je lahko ime datoteke ali mape (npr. os.path.join("P1", "os", "resitev.py") vrne niz "P1\\os\\resitev.py" na OS Windows oziroma "P1/os/resitev.py" na OS Linux in MacOS)Trenutno preverjenje ne deluje (ker ni ustrezne datoteke) Vsaka rešitev je javljena kot pravilna! Za preverjanje nalog v imenik/mapo, kjer imate rešitve, skopirajte
ZIP datoteko
in jo razširite (nastala bo mapa PythonOsRek s podmapami testX in
EURO2012)
Sestavite funkcijo seznam_vseh_podmap(zacetna_mapa), ki vrne seznam poti do
vseh map (vključno z začetno), ki jih vsebuje zacetna_mapa. Če
zacetna_mapa ni veljavno ime mape, naj funkcija vrne None.
>>>> seznam_vseh_podmap('.\\PythonOSRek\\test4')
['.\\PythonOSRek\\test4', '.\\PythonOSRek\\test4\\test3',
'.\\PythonOSRek\\test4\\New folder', '.\\PythonOSRek\\test4\\test3\\New folder']
Namig: Ali pot predstavlja mapo oz. datoteko preverimo z os.path.isdir.
Poti med seboj združujemo z os.path.join, da lahko program uporabljamo na
različnih operacijskih sistemih.
Sestavite funkcijo mape_ki_vsebujejo_datoteko(zacetna_mapa, datoteka), ki
vrne urejen seznam vseh map, ki vsebujejo dano datoteko. Pri tem naj iskanje
prične v začetni mapi.
>>>> mape_ki_vsebujejo_datoteko('.\\PythonOSRek\\test1', 'drevo.py')
['.\\PythonOSRek\\test1', '.\\PythonOSRek\\test1\\PodM\\TraRa']
Če mapa ne opisuje poti do mape, naj funkcija vrne None.
Sestavite funkcijo koliko_datotek, ki prešteje, koliko je vseh datotek v
izbrani mapi. Pri tem naj šteje tudi datoteke v podmapah, map pa naj ne
šteje. ČeCheck.feedback("Funkcija izpisi_datoteke trenutno nima testov, zato morate za testiranje rešitve poskrbeti sami.")
podana pot ne opisuje mape, naj funkcija vrne None.
>>>> koliko_datotek('.\\PythonOSRek\\test1')
46
Sestavite funkcijo vrni_python_datoteke, ki vrne po abecedi urejen seznam
(polnih) imen vseh datotek v izbrani mapi in njenih podmapah, ki imajo
končnico .py.
Namig: Za pridobivanje končnice lahko uporabite metodo os.path.splitext.
Naloga nima testnega programa! V Tomu so le zato, da so "na kupu"
Vsaka oddaja bo označena kot pravilna!
Izpiši mapo
Sestavi funkcijo izpisi_datoteke(pot_do_mape), ki izpiše vse datoteke
v izbrani mapi in njenih podmapah.
Funkcija naj izpisuje samo imena datotek, brez poti.
Uporabi izpis z zamikanjem, da bo razvidno, kateri mapi pripada
katera datoteka. Vedno najprej izpiši datoteke, potem mape.
a.txt
tra.py
bla
dat.txt
ble
blu
c.dat
xxx
yyy
e.dat
Sestavi funkcijo izpisi_py(pot_do_mape), ki izpiše imena vseh
datotek v izbrani mapi in njenih podmapah, ki imajo končnico .py.
Izpisuje naj polna imena (skupaj s potjo).
Sestavi funkcijo izbrisi_prazne_mape(pot_do_mape),
ki v izbrani mapi (in njenih podmapah) pobriše vse prazne datoteke
(tiste z velikostjo 0) in vse prazne mape (tiste, ki ne vsebujejo nobenih
datotek ali podmap). Funkcija naj vrne par, ki ga sestavljata število
pobrisanih datotek in število pobrisanih map, oziroma None, če pot_do_mape
ne opisuje imenika.
Pozor: ko zbrišemo prazno datoteko, se lahko sprazni tudi mapa.
TRENUTNO TESTIRANJE NE DELA!
Pred testiranjem vedno skopirajte to
datoteko ZIP
(staro mapo PythonOsRek pobrišite!)
in jo razširite (nastala bo mapa PythonOsRek s podmapami testX in EURO2012)
Trenutno preverjenje ne deluje (ker ni ustrezne datoteke) Vsaka rešitev je javljena kot pravilna! Za preverjanje nalog v imenik/mapo, kjer imate rešitve, skopirajte
Za preverjanje nalog v imenik/mapo, kjer imate rešitve, skopirajte ZIP datoteko in jo razširite (v mapo, v kateri se nahaja pythonova datoteka z nalogami).
Namig: naloge se vam splača reševati tako, da najprej definirate delovanje funkcij v trenutni mapi, potem pa jih rekurzino pokličete še na vseh podmapah. Uporabljajte relativne poti.
Sestavi funkcijo poisci_velike(pot_do_mape, velikost),
ki vrne seznam polnih imen datotek v dani mapi in njenih podmapah,
katerih velikost je večja ali enaka dani vrednosti. Če je mapa prazna,
naj funkcija vrne prazen seznam.
>>> poisci_velike('mapa_1', 2000)
['mapa_1\\mapa_1_1\\jovo_datoteka.txt', 'mapa_1\\mapa_1_3_abc\\bn_datoteka_556.txt']
Sestavi funkcijo poisci_poti(pot_do_mape,ime_datoteke), ki
vrne seznam vseh poti, ki vodijo do dane datoteke.
>>> poisci_poti('mapa_1', 'z_datoteka_1_2_e.txt')
['mapa_1\\z_datoteka_1_2_e.txt', 'mapa_1\\mapa_1_1\\z_datoteka_1_2_e.txt']
Sestavi funkcijo najstevilcnejsa(pot_do_mape), ki v izbrani mapi (in njenih
podmapah) poišče mapo, ki vsebuje največ datotek (štejemo samo datoteke v
mapi, ne tudi v podmapah, saj je drugače naloga nesmiselna). Funkcija naj vrne
ime iskane mape (skupaj s potjo) ter število datotek v tej mapi. Če je mapa
prazna, naj funkcija vrne (None, 0).
>>> najstevilcnejsa('mapa_1')
('mapa_1\\mapa_1_1', 4)
>>> najstevilcnejsa('mapa_1\\mapa_1_2')
(None, 0)
Poišči vse najnovejše datoteke.
Sestavi funkcijo poisci_najnovejse(pot_do_mape), ki v izbrani mapi
(in njenih podmapah) poišče datoteke, ki so bile zadnje spremenjene.
Funkcija naj vrne tabelo imen teh datotek (skupaj s potjo).
>>> poisci_najnovejse('mapa_1')
['mapa_1\\z_datoteka_1_2_e.txt', 'mapa_1\\mapa_1_1\\z_datoteka_1_2_e.txt', 'mapa_1\\mapa_1_3_abc\\arrested.txt']
Poišči najnovejšo datoteko.
Sestavi funkcijo poisci_najnovejso_abeceda(pot_do_mape), ki v izbrani mapi
(in njenih podmapah) poišče datoteko, ki je bila zadnja spremenjena, in
vrne njeno polno ime (skupaj s potjo). Če je takih datotek več, naj funkcija
vrne ime datoteke, ki je prva po abecedi.
>>> poisci_najnovejso_abeceda('mapa_1')
'mapa_1\\mapa_1_1\\z_datoteka_1_2_e.txt'
Poišči največjo datoteko.
Sestavi funkcijo najvecja(pot_do_mape), ki v izbrani mapi (in njenih
podmapah) poišče največjo datoteko. Funkcija naj vrne par, ki ga sestavljata
po abecedi zadnje ime take datoteke (skupaj s potjo) in njena velikost.
>>> najvecja('mapa_1')
('mapa_1\\mapa_1_3_abc\\bn_datoteka_556.txt', 6120)
Naloge nimajo testnega programa! V Tomu so le zato, da so "na kupu". Vsaka oddaja bo označena kot pravilna!
Če uporabite datotečno strukturo iz datoteke ZIP, kot je opisana pri nalogi Pregled map in datotek, naj se vaše funkcije obnašajo, kot kažejo zgledi!
Naloga je namenoma ZELO PODOBNA nalogi Iskanje. Le testna ZIP datoteka je drugačna ter sem in tja spremenjena kakšna malenkost. Poskusite nalogi rešiti na različne načine.
Sestavi funkcijo izpisi_velike(pot_do_mape, velikost),
ki vrne seznam polnih imen datotek v dani mapi in njenih podmapah,
katerih velikost je večja ali enaka dani vrednosti.
Sestavi funkcijo izpisi_mapet(pot_do_mape,imeDatoteke), ki
izpiše vse mape, ki vsebujejo dano datoteko.
>>> izpisi_mapet('.\\PythonOSrek', 'drevo.py')
.\PythonOSrek\test1\drevo.py
.\PythonOSrek\test1\podM\TraRa\drevo.py
.\PythonOSrek\test1a\drevo.py
.\PythonOSrek\test1a\podM\TraRa\drevo.py
Sestavi funkcijo najstevilcnejsa(pot_do_mape), ki v izbrani mapi (in njenih
podmapah) poišče mapo, ki vsebuje največ datotek (štejemo samo datoteke v
mapi, ne tudi v podmapah, saj je drugače naloga nesmiselna). Funkcija naj vrne
ime iskane mape (skupaj s potjo) ter število datotek v tej mapi.
>>> najstevilcnejsa('.\\PythonOSrek')
('.\\PythonOSrek\\test1', 7)
Poišči najnovejšo datoteko.
Sestavi funkcijo poisci_najnovejse(pot_do_mape), ki v izbrani mapi
(in njenih podmapah) poišče datoteke, ki so bile zadnje spremenjene.
Funkcija naj vrne tabelo imen teh datotek (skupaj s potjo).
>>> poisci_najnovejse('.\\PythonOSrek')
['.\\PythonOSrek\\EURO2012\\euro database.py']
Poišči najnovejšo datoteko.
Sestavi funkcijo poisci_najnovejse(pot_do_mape), ki v izbrani mapi
(in njenih podmapah) poišče datoteko, ki so bile zadnja spremenjena.
Funkcija naj vrne po abecedi najmanjše ime izmed teh datotek (skupaj s potjo).
>>> poisci_najnovejse('.\\PythonOSrek')
'.\\PythonOSrek\\EURO2012\\euro database.py'
Poišči največjo datoteko.
Sestavi funkcijo najvecja(pot_do_mape), ki v izbrani mapi (in njenih
podmapah) poišče največjo datoteko. Funkcija naj vrne par, ki ga sestavljata
po abecedi zadnje ime take datoteke (skupaj s potjo) in njena velikost.
>>> najvecja('.\\PythonOSrek')
('.\\PythonOSrek\\test1\\Tips.PNG', 94535)
Trenutno testi ne delujejo. Vse naloge bodo označene kot pravilne!
Tomo bo pravilnost vaših rešitev preverjal na datotekah, ki jih najdete stisnjene v tej ZIP datoteki. Stisnjeno datoteko razširite v isto mapo, kjer se nahaja vaš program.
Sestavi funkcijo poisci_datoteke(pot_do_mape), ki vrne seznam vseh datotek
(njihova imena brez poti) v izbrani mapi in njenih podmapah. Za vsako podmapo
naj funkcija seznamu doda par (ime podmape, [seznam datotek]). Če podmapa vsebuje
še dodatne podmape, naj se par globje podmape vgnezdi v seznam datotek
prvotne podmape. Funkcija naj v seznam vedno najprej doda imena datotek,
šele potem pare s podmapami.
>>> poisci_datoteke('mapa_2')
['datoteka_1_1_abcd.txt', 'dolzina_vektorja.py', 'z_datoteka_1_2_e.txt', ('mapa_1_1', ['32_datoteka.txt', 'ar_datoteka_jk.txt', 'jovo_datoteka.txt', 'program_445.py', 'z_datoteka_1_2_e.txt', ('gh_mapa_zadnja', ['nova_datoteka.txt', 'test_datoteka.txt', 'zivi_program.py'])]), ('mapa_1_2', []), ('mapa_1_3_abc', ['arrested.txt', 'bn_datoteka_556.txt', 'ddatoteka.txt', 'zeta_funkcija.py'])]
Sestavi funkcijo izpisi_datoteke(), ki vpraša po imenu (oz. relativni poti)
mape in izpiše vse datoteke
v izbrani mapi in njenih podmapah.
Funkcija naj izpisuje samo imena datotek, brez poti.
Izpiše naj tudi imena podmap, imena datotek v njih pa naj izpiše z zamikom,
da bo izpis bolj pregleden.
Za vsak nov nivo podmape naj izpis zamakne za dodatna dva presledka.
Vedno najprej izpiši imena datotek, šele potem imena podmap. Če si rešil
zgornjo nalogo, lahko zgolj predelaš njeno rešitev.
Po definiciji funkcije jo še pokliči brez argumentov (da bo Tomo lahko preveril rešitev; ta vrstica je že dodana).
Namig: Tomo bo med preverjanjem klical funkcijo brez argumentov. To pa še ne pomeni, da funkcija ne sme sprejemati argumentov. Lahko jih, dokler so ti argumenti neobvezni (to pomeni, da imajo predpisano privzeto vrednost).
>>> izpisi_datoteke()
Pot do mape: mapa_2
datoteka_1_1_abcd.txt
dolzina_vektorja.py
z_datoteka_1_2_e.txt
mapa_1_1
32_datoteka.txt
ar_datoteka_jk.txt
jovo_datoteka.txt
program_445.py
z_datoteka_1_2_e.txt
gh_mapa_zadnja
nova_datoteka.txt
test_datoteka.txt
zivi_program.py
mapa_1_2
mapa_1_3_abc
arrested.txt
bn_datoteka_556.txt
ddatoteka.txt
zeta_funkcija.py
>>>
Sestavi funkcijo poisci_datoteke(pot_do_mape, koncnica), ki vrne seznam vseh
datotek (njihova imena skupaj s potjo) v izbrani mapi in njenih podmapah,
ki imajo končnico koncnica (npr. .txt, .xlsx, ..). Privzeta končnica naj
bo .txt.
>>> poisci_datoteke('mapa_2', '.py')
['mapa_2\\dolzina_vektorja.py', 'mapa_2\\mapa_1_1\\program_445.py', 'mapa_2\\mapa_1_1\\gh_mapa_zadnja\\zivi_program.py', 'mapa_2\\mapa_1_3_abc\\zeta_funkcija.py']
Na vsakem zanimivem igrišču za golf so ovire: jezero, pesek, ...
Jezero je krog, podan kot trojica (x,y,r). x in y sta koordinati središča,
r pa polmer.
Pesek je pravokotnik, podan kot četverica(x1,y1,x2,y2). Predpostaviš lahko, da
so to po vrsti koordinate levega spodnjega in desnega zgornjega oglišča.
Vse koordinate računamo na tri decimalke.
Na datoteki imamo zapisane podatke o posameznih udarcih v obliki polarnih koordinat (kot
je podan v stopinjah).
V vsaki vrstici sta zapisani celi števili r in fi, ločeni s presledkom.
Napišite funkcijo datoteka_polozajev(vhod, izhod), ki naj prebere datoteko vhod in
ustvari novo datoteko izhod tako, da je v vsaki vrstici zapisan trenutni položaj žogice
(v obliki decimalnih števil, zaokroženih na 3 decimalna mesta)
in ločenih s presledkom. V ta namen uporabite formatiranje z f-nizi.
Začetni položaj žogice naj bo v točki (0,0).
Podan je seznam položajev žogic po posameznem udarcu in seznam, katerega vsak element
je nabor, ki podaja jezero ali pesek. Napišite metodo se_izogne(pot, ovire), ki pove, ali
se pot v celoti izogne oviram. Pazi: jezero je podano z naborom treh, pesek pa z naborom štirih števil.
Najprej napišite metodi je_v_jezeru(zogica, jezero) in je_v_pesku(zogica, pesek), ki
povesta, ali je žogica v jezeru ali v pesku. Žogica je podana kot par (x,y), torej "nima dimenzije".
Napišite metodo kje_je_zogica(datoteka, zacetek, ovire), ki
vrne vektor od začenega do končnega položaja ali None,
če žogica kdaj vmes pade v oviro. Vektor naj bo zaokrožen na
3 decimalna mesta.
Posamezni udarci so v polarnih koordinatah zapisani na datoteko, začetek pa je
podan kot par (x,y).
V datoteki imamo zapisane podatke o vrednosti neke delnice. V vsaki vrstici je zapisan podatek v obliki
YYYY-MM-DD,vrednost
kjer je prvi podatek dan, drugi pa vrednost delnice na ta dan.
Sestavite funkcijo preberi(ime_datoteke), ki kot parameter sprejme
ime datoteke, vrne par nabor dveh seznamov, v prvem naj bodo datumi
(kot nizi), v drugem pa vrednosti delnice (kot realna števila).
Logaritemski povratek delnice je definiran kot logaritem kvocienta vrednosti delnice za dva zaporedna dneva trgovanja:
Zakaj je to uporabno
Sestavite funkcijo
povratek(ime_dat), ki kot parameter sprejme ime datoteke z vrednostmi delnice.
in vrne seznam logaritemskih povratkov. Če je
podana datoteka prazna ali pa vsebuje le en podatek, naj funkcija vrne prazen
seznam.
Iz logaritemskih povratkov lahko razberemo, ali je vrednost delnice
naraščala ali padala. Sestavite funkcijo trend(povratki), ki sprejme
seznam logaritemskih povratkov in vrne niz pozitiven trend, če je
v seznamu več pozitivnih vrednosti kot negativnih, sicer pa naj vrne
negativen trend. Vrednosti 0 štejte k negativnim.
Letna volatilnost
delnice (Volatilnost ali nihajnost označuje, koliko je statistično verjetno, da
cena delnice v kratkem času močneje zraste ali pade)
je definirana kot večkratnik standardnega
odklona logaritemskega povratka:
kjer je povprečna vrednost logaritemskih povratkov, so posamezni logaritemski
povratki, je število logaritemskih povratkov, 252 pa predstavlja
število trgovalnih dni v letu.
Sestavite funkcijo volatilnost(ime_datoteke), ki iz datoteke prebere
vrednosti delnice in vrne njeno letno volatilnost .
Uporabite ustrezno kodiranje (UTF8 ali CP1250), lahko tudi različno pri različnih podnalogah!
Sestavite funkcijo html2txt(vhod, izhod), ki bo vsebino datoteke z
imenom vhod prepisala v datoteko z imenom izhod, pri tem pa odstranila
vse značke. Vemo, da je datoteka HTML sestavljena prav!
Značke se začnejo z znakom < in končajo z znakom >. Pozor: Začetek in
konec značke nista nujno v isti vrstici. Takrat se vrstica nadaljuje!
Prav tako ima lahko značka lastnosti, npr. značka a ima lastnost href
<a href = "kk.htm">
Na primer, če je v datoteki vreme.html zapisano:
<h1>Napoved vremena</h1>
<p>Jutri bo <i><b>lepo</b></i> vreme.
Več o vremenu preberite <a
href="napoved.html">tukaj</a>.</p>
bo po klicu html2txt('vreme.html', 'vreme.txt') v datoteki vreme.txt
zapisano (pozor na tretjo vrstico!):
Napoved vremena
Jutri bo lepo vreme.
Več o vremenu preberite tukaj.
Sestavite funkcijo tabela(vhod, izhod), ki bo podatke iz vhodne
datoteke zapisala v obliki HTML tabele v izhodno datoteko.
V vhodni datoteki so podatki shranjeni po vrsticah ter ločeni z vejicami.
Na primer, če je v datoteki tabela.txt zapisano:
ena,dva,tri
17,52,49.4,6
abc,xyz
bo po klicu tabela('tabela.txt', 'tabela.html') v datoteki tabela.html:
<table>
<tr>
<td>ena</td>
<td>dva</td>
<td>tri</td>
</tr>
<tr>
<td>17</td>
<td>52</td>
<td>49.4</td>
<td>6</td>
</tr>
<tr>
<td>abc</td>
<td>xyz</td>
</tr>
</table>
Pozor: Pazi na zamik (število presledkov na začetku vrstic) v izhodni datoteki.
Sestavite funkcijo seznami(vhod, izhod), ki bo podatke iz vhodne
datoteke zapisala v izhodno datoteko v obliki neurejenega seznama. V
vhodni datoteki se vrstice seznamov začnejo z zvezdico. Temu lahko sledi
nekaj presledkov, nato pa element seznama
Na primer, če je v datoteki seznami.txt zapisano:
V trgovini moram kupiti:
*jajca,
* kruh,
* moko.
Na poti nazaj moram:
* obiskati sosedo.
bo po klicu seznami('seznami.txt', 'seznami.html') v datoteki seznami.html:
V trgovini moram kupiti:
<ul>
<li>jajca,</li>
<li>kruh,</li>
<li>moko.</li>
</ul>
Na poti nazaj moram:
<ul>
<li>obiskati sosedo.</li>
</ul>
Sestavite funkcijo gnezdeni_seznami(vhod, izhod), ki bo podatke iz
vhodne datoteke zapisala v izhodno datoteko v obliki neurejenega gnezdenega
seznama. V vhodni datoteki je vsak element seznama v svoji vrstici, zamik
pred elementom pa določa, kako globoko je element gnezden.
Na primer, če je v datoteki seznami.txt zapisano:
živali
sesalci
slon
ptiči
sinička
rastline
sobne rastline
difenbahija
bo po klicu gnezdeni_seznami('seznami.txt', 'seznami.html') v datoteki
seznami.html zapisano:
<ul>
<li>živali
<ul>
<li>sesalci
<ul>
<li>slon
</ul>
<li>ptiči
<ul>
<li>sinička
</ul>
</ul>
<li>rastline
<ul>
<li>sobne rastline
<ul>
<li>difenbahija
</ul>
</ul>
</ul>
Značk <li> ne zapirajte.
Napišite funkcijo cas_maratona(niz), ki sprejme niz z doseženim
časom na kolesarskem maratonu v obliki 'ure:minute:sekunde' in vrne
ta čas v obliki tabele s tremi elementi: [ure, minute, sekunde].
Predpostavite, da so vrednosti v nizu smiselne. Primer:
>>> cas_maratona('4:13:59')
[4, 13, 59]
Napišite funkcijo vsi_casi(ime_datoteke), ki prebere vhodno datoteko,
v kateri so shranjeni časi tekmovalcev in vrne tabelo trojčkov s temi
časi. Vsaka vrstica vsebuje čas enega tekmovalca. Uporabite rešitev prve
podnaloge!
Primer datoteke (maraton.txt):
4:13:59
5:45:12
3:17:25
8:4:35
2:58:26
3:1:15
Primer uporabe za zgornjo datoteko:
>>> vsi_casi('maraton.txt')
[[4, 13, 59], [5, 45, 12], [3, 17, 25], [8, 4, 35], [2, 58, 26], [3, 1, 15]]
Napišite funkcijo nagrajeni(ime_datoteke, ura, minuta, sekunda),
ki prebere čase tekmovalcev iz datoteke ter vrne število nagrajenih
tekmovalcev (to so tisti, ki so dosegli enak ali boljši čas od podanega).
Vhodna datoteka ima takšno obliko, kot je opisano v drugi podnalogi.
Uporabite rešitev druge podnaloge!
Primer uporabe za datoteko iz druge podnaloge:
>>> nagrajeni('maraton.txt', 4, 0, 0)
3
Napišite funkcijo urejeni_casi(ime_vhodne, ime_izhodne), ki prebere
čase iz vhodne datoteke, jih uredi v naraščajočem vrstnem redu ter
urejene zapiše v izhodno datoteko. Vhodna in izhodna datoteka imata
enako obliko, tako kot je opisano v drugi podnalogi. Uporabite rešitev
druge podnaloge!
Primer vhodne datoteke (maraton.txt):
4:13:59
5:45:12
3:17:25
8:4:35
2:58:26
3:1:15
Po klicu funkcije urejeni_casi('maraton.txt', 'urejeno.txt') mora imeti
izhodna datoteka (urejeno.txt) naslednjo vsebino:
2:58:26
3:1:15
3:17:25
4:13:59
5:45:12
8:4:35
Nasvet 1: Uporabite vgrajeno funkcijo sort, ki zna sortirati tudi
gnezdene tabele (v vašem primeru tabele trojčkov).
Nasvet 2: Pri oblikovanju vrstic izhodne datoteke si lahko pomagate s
funkcijo join!
S tekmovanja RTK 2014
V računalniškem sistemu imamo zabeležene dogodke in bi jih radi v strnjeni obliki shranjevali v seznam nizov. Vsak dogodek (kot na primer prijava ali odjava uporabnika, razne napake) je predstavljen z nizom znakov (kratko besedilo/vrstica), dolžine največ . Dogodki so zapisani v vhodni datoteki, po en dogodek v vsaki vrstici.
Ker se nekateri dogodki včasih zgodijo večkrat zapored (ne da bi se vmes zgodil kakšen drug dogodek), jih lahko shranimo v skrajšani obliki: ponovitve zadnjega shranjenega dogodka le štejemo. Ko se kasneje pojavi nek drugačen dogodek, shranimo le, da se je zadnji shranjen dogodek ponovil še -krat. V primeru, da gre le za eno dodatno ponovitev (, torej skupaj s prvo izpisano pojavitvijo dve pojavitvi, glej zgled), namesto sporočila o ponovitvi shranimo kar sam ponovljeni dogodek, saj ne bi s sporočilom o ponovitvi nič prihranili.
Napisana je funkcija strni_izpis(datot), ki naj bi brala dogodke iz vhodne
datoteke in jih shranjevala v seznam nizov. Vendar pa je v programu nekaj
napak, zaradi katerih ne deluje. Popravi napake v kodi.
def strni_izpis(datot):
prejsnja = ""
n = 0
dat = with open(datot,'w', encoding='utf-8')
dat = dat.readlines()
sez_strnjenih = []
for dogodek in dat:
if n > 0 and prejsnja != dogodek:
n += 2
continue
if n == 1:
sez_strnjenih.append("%s" % prejsnja[:-1])
elif n > 2:
sez_strnjenih.append("ponovljeno se %d-krat" % (n))
prejsnja = dogodek
n = 1
if dogodek:
sez_strnjenih.append(dogodek[0])
return sez_strnjenih
Tekstovna datoteka dogodki.txt z zaporedjem dogodkov. Datoteka je kodirana v
utf-8.
Primer:
aaa
aaa
bbbbb
ccc
ccc
ccc
dd
dd
aaa
aaa
aaa
aaa
Funkcija naj vrne seznam nizov, v katerem so strnjeni dogodki.
>>> strni_izpis(dogodki.txt)
['aaa', 'aaa', 'bbbbb', 'ccc', 'ponovljeno se 2-krat', 'dd', 'dd', 'aaa', 'ponovljeno se 3-krat']
S tekmovanja RTK 2013
V devetnajstem stoletju se še ni kaj dosti vedelo o načinu prenašanja nalezljivih bolezni. Leta so imeli v Londonu velik izbruh črevesne bolezni kolere. Zdravnik John Snow je takrat s svojo analizo pokazal na vzročno zvezo med lokacijo londonskih vodnjakov in lokacijo domovanja obolelih. Izkazalo se je, da so žrtve pile vodo iz istega okuženega vodnjaka na ulici Broad Street. Zdravnik si je narisal zemljevid Londona, vanj vrisal lokacije vodnjakov in za vsak vodnjak z drugo barvo pobarval območje zemljevida, ki je temu vodnjaku najbližje. Ko je vrisal še točke domovanja obolelih, je postala vzročna zveza precej očitna, saj so prebivalci večinoma hodili po vodo k njim najbližjemu vodnjaku.
Nekoliko si poenostavimo zemljevid velemesta in denimo, da nas zanima le območje, ki ga razdelimo na kvadratno mrežo celic. V nekaterih celicah te mreže se nahajajo vodnjaki. Vseh vodnjakov je deset, njihove koordinate preberemo iz vhodne datoteke: v vsaki vrstici sta dve celi števili, in (obe sta z območja od do ).
Dopolni funkcijo povrsine_vodnjakov(koordinate_vodnjakov),
ki bo prebrala koordinate vodnjakov, potem pa vrnila
seznam površin posameznih vodnjakov, tj. seznam s številom celic, za
katere velja, da jim je v tej pravokotni mreži ta vodnjak najbližji.
def povrsine_vodnjakov(koordinate_vodnjakov):
"""Za vodnjake v vhodni datoteki izračuna, kolikšna površina pripada vsakemu vodnjaku in vrne seznam površin."""
vodnjaki = []
with open(koordinate_vodnjakov, 'r') as vhod:
# Shranimo koordinate vodnjakov
for vrstica in vhod:
(x, y) = vrstica.###.split(' ')
vodnjaki.append((int(x), int(y)))
povrsine = len(vodnjaki) * [0]
# Za vsako celico poiščemo najbližji vodnjak
for y in range():
for x in range(1, 51):
najkrajsa = 50 * 50 + 50 * 50 # vsak kvadrat razdalje dveh celic bo manjši od tega
naj_vodnjak = 0
for i in range(len(vodnjaki)):
vodnjak = vodnjaki[i]
razdalja = ###
# Če je celica bližje temu vodnjaku od doslej najbližjega vodnjaka, si to zapomnimo
if vodnjak == vodnjaki[0] or razdalja < najkrajsa:
najkrajsa = razdalja
naj_vodnjak = i
### += 1
return povrsine
Za merjenje razdalje med dvema celicama uporabimo Pitagorov izrek:
kvadrat razdalje med in je
. Če je od neke celice razdalja do
več vodnjakov enaka, tako celico štejemo k vodnjaku, ki ga v datoteki
najdemo prej (datoteko beremo od začetka proti koncu).
Celico, v kateri je vodnjak, štejemo k vodnjaku, ki stoji v tej celici.
Tvoja funkcija naj bere iz datoteke kolera.txt.
Funkciji kot parameter podamo datoteko kolera.txt, v kateri so
koordinate vodnjakov.
Seznam dolg kolikor je vodnjakov, v katerem je na mestu število celic, ki pripadajo -temu vodnjaku.
Primer vhodnih podatkov (iz datoteke):
49 5
33 8
1 27
23 43
25 45
12 8
10 29
3 5
23 6
12 32
Primer izhodnega podatka glede na zgornje vhodne podatke:
>>> povrsine_vodnjakov('kolera.txt')
[240, 420, 115, 325, 452, 206, 158, 97, 184, 303]
V datoteki imamo zapisane račune, vsak se začne z vrstico oblike 'RačunNNNNN',
kjer je NNNNN zaporedna številka računa. Kupljeni izdelki so zapisani v
naslednjih vrsticah v obliki "izdelek:kolicina:cena_enega".
Sestavite funkcijo preberi(datoteka), ki iz datoteke prebere račune in jih
kot slovarje shrani v tabelo. Slovarji naj imajo za ključe izdelke, za
vrednosti pa pare (kolicina, cena_za_vse).
Če je v datoteki zapisano:
Račun23421
vino:2:10
voda:1:2
Račun64529
parfum:1:30
voda:5:2
čips:2:2.5
Naj funkcija vrne:
>>> preberi(datoteka)
[{'vino': (2, 20), 'voda':(1, 2)}, {'parfum': (1, 30), 'voda': (5, 10), 'čips': (2, 5)}]
Sestavite funkcijo prodaja(ime_datoteke), ki bo iz datoteke kot prej prebrala
račune in vrnila par: (zasluzek, prodano), kjer je zasluzek vsota zasluženega
denarja, prodano pa nov slovar, v katerem so ključi izdelki, vrednosti pa število
prodanih tovrstih izdelkov.
Franci zelo rad gleda filme. Ker ne razume tujih jezikov, si s strani
podnapisi.net sname podnapise. Datoteke s
podnapisi (ki imajo končnico .srt) so takšne oblike:
1
00:08:51,520 --> 00:08:53,317
Pa je šla nevesta!
2
00:14:03,920 --> 00:14:08,357
Jebi ga, jaz bi ti pomagal,
samo šofer, Slovenec...
3
01:18:07,640 --> 01:18:12,589
Ima ta tvoja Špela na desni
joški materino znamenje? Ima?!
4
01:18:17,040 --> 01:18:22,194
Jebi ga, Božo.
Umiri malo žogo.
Za nas bo beseda podnapisi pomenila zaporedje manjših enot, ki jim bomo rekli napisi. Napisi so med seboj ločeni s po eno prazno vrstico. Vsak napis je sestavljen iz treh ali več vrstic. V prvi vrstici je zaporedna številka napisa, v drugi čas trajanja, od tretje dalje pa je besedilo.
Ker podnapise delajo amaterji, se včasih zgodi, da na neki točki začnejo podnapisi zaostajati ali pa prehitevati. To gre Franciju zelo na k████. Če boste sestavili program, ki bo sposoben podnapise popraviti, se vam obeta gajba …
Opomba: Zgornji zgled je iz filma Kajmak in marmelada.
Sestavite funkcijo pretvori(h, m, s, milis), ki dobi čas v urah,
minutah, sekundah in milisekundah ter ga preračuna v milisekunde.
Zgled:
>>> pretvori(1, 18, 7, 640)
4687640
Sestavite še funkcijo pretvori_nazaj(milis), ki naredi ravno obratno
kot funkcija pretvori, tj. dobi čas v milisekundah in ga preračuna v
ure, minute, sekunde in milisekunde. Primer:
>>> pretvori_nazaj(4687640)
(1, 18, 7, 640)
Sestavite funkcijo popravi(vhod, izhod, t, d), ki kot argumente dobi:
Funkcija naj prebere podnapise iz datoteke z imenom vhod in naj na
datoteko z imenom izhod izpiše popravljene podnapise, tako da vse
čase, ki so kasnejši od t, premakne za d milisekund naprej. Če je
slučajno d negativno število, se časi seveda premaknejo nazaj.
Predpostavite lahko, da se preskok nikoli ne zgodi sredi napisa, ampak
vedno v vmesnem času.
Obe datoteki sta kodirani v UTF-8. Pri odpiranju datotek uporabite
imenovani argument encoding, s katerim eksplicitno navedete kodno
tabelo, takole: open(vhod, encoding='utf-8').
Primer: Če je na datoteki kajmak.srt primer z začetka opisa naloge, naj bo po klicu funkcije
>>> popravi('kajmak.srt', 'popravljeno.srt', 3600000, 120000)
v datoteki popravljeno.srt besedilo:
1
00:08:51,520 --> 00:08:53,317
Pa je šla nevesta!
2
00:14:03,920 --> 00:14:08,357
Jebi ga, jaz bi ti pomagal,
samo šofer, Slovenec...
3
01:20:07,640 --> 01:20:12,589
Ima ta tvoja Špela na desni
joški materino znamenje? Ima?!
4
01:20:17,040 --> 01:20:22,194
Jebi ga, Božo.
Umiri malo žogo.
lastnosti /property/
Pri preprostih razredih pogosto upravljamo direktno z lastnostmi objektov. Če
želimo točko s koordinatama x in y premakniti za vektor (1, 0) to
storimo tako, da popravimo koordinati. V mnogih primerih pa imajo lastnosti
objektov omejitve, ali pa preprosto želimo abstrakcijo implementacije.
V teh primerih do lastnosti ne dostopamo direktno (takšne lastnosti
predznačimo z _), temveč za njih spišem posebne metode za dostop. Za lažje
delo v Pythonu uporabljamo dekorator @property, ki ga bomo spoznali v
naslednjih podnalogah.
Točko v polarnih koordinatah podamo s kotom in razdaljo od izhodišča. Pri tem je razdalja nujno pozitivna, kot pa leži na intervalu .
Definirajte razred SlabaPolarnaTocka, za katero definirajte metodo
__init__(self, r, phi), ki ustvari. Če je razdalja r negativna, jo
nastavimo na 0, na kot phi pa gledamo modulo .
>>> a = SlabaPolarnaTocka(-10, 4)
>>> a.r
0
>>> a.phi
Napišite primer pokvarjena_tocka, ki pripada razredu SlabaPolarnaTocka
ampak ima razdaljo r negativno.
Namig: Ustvarite poljubno točko, in jo pokvarite.
>>> pokvarjena_tocka.r < 0
True
Napišite razred BoljsaPolarnaTocka, ki ima namesto lastnosti r lastnost
_r (podrčtaj označuje, da je uporabnik ne sme direktno spreminjati). Za
dostop do razdalje definirajte metodi nastavi_r(self, r) in
vrednost_r(self), ki pravilno upravljata z lastnostjo _r. Metoda
__init__ naj že uporablja ti dve metodi za kreacijo točke.
Opomba: Za kot točke se trenutno ne zmenimo (lahko ga tudi izpustite).
>>> a = BoljsaPolarnaTocka(-10, 0)
0
>>> a.nastavi_r(5)
>>> a.vrednost_r()
5
Uporaba dodatnih metod za dostop do lastnosti je naporna, zato problem rešimo
z dekoratorjem @property. Razred PolarnaTocka ze uporablja @property za
razdaljo, vaša naloga pa je, da ta pristop uporabite še za kot.
Če lastnosti definiramo na takšen način, jih lahko uporabljamo kot običajno.
Opomba: Metoda za prikaz vrednosti lastnosti uporablja dekorator @property,
metoda za nastavljanje vrednosti pa @ime_lastnosti.setter.
>>> a = PolarnaTocka(-5, 10)
>>> a.phi
0.5752220392306207
>>> a.phi = -2
>>> a.phi
1.1415926535897931
Sestavljen je razred KompleksnoStevilo z metodama __init__(self, re, im),
lastnostima im in re ter __repr__(self).
Realni del kompleksnega števila je shranjen v spremenljivki
_re, imaginarni pa v _im. Metoda __repr__(self) predstavi kompleksno
število z nizom oblike KompleksnoStevilo(re, im).
Zgled:
>>> u = KompleksnoStevilo(3, 4)
>>> u
KompleksnoStevilo(3, 4)
Žal so se vrstice v kodi zamešale. uredi jih v pravilni vrstni red. Razen spreminanja vrstnega reda ne naredi nobene druge spremembe
Razred Ulomki (osnova) iz sklopa Uvod v OOP bomo nadgradili z lastnostmi.
Skopirajte svojo implementacijo razreda Ulomek iz sklopa Uvod v OOP in jo
dopolnite po navodilih.
Sestavite razred Ulomek, s katerim predstavimo ulomek. Števec in
imenovalec sta celi števili, pri čemer je imenovalec vedno pozitiven.
Ulomki naj bodo vedno okrajšani.
Do števca lahko pridemo preko lastnosti st, do imenovalca pa preko lastnosti
im. Če poskusimo spremeniti števec ali imenovalec (torej lastnosti st ali im)
naj koda sproži napako z obvestilom "Obstoječega ulomka ne moremo spreminjati".
Namig: veljavnost argumentov preverite v metodi __init__, setter metodi (recimo st.setter) pa
naj poskrbita, da vrednosti ne moremo pokvariti.
Tudi metodi __str__ in __repr__ popravite tako, da bosta do vrednosti
dostopali preko lastnosti (property) in ne direktno preko "privatnih" atributov.
Zgled:
>>> u = Ulomek(5, -20)
>>> u.st
-1
>>> u.im
4
>>> u.st = 4
... Exception("Obstoječega ulomka ne moremo spreminjati")
Kot pri nalogi Polinomi v sklopu Uvod v OOP
sestavite razred Polinom, s katerim predstavimo polinom v
spremenljivki .
Polinom predstavimo s tabelo njegovih koeficientov,
kjer je -ti element tabele koeficient pri .
Na primer, polinom predstavimo s Polinom([7, 2, 0, 1]).
Razmislite, kaj predstavlja Polinom([]). Zadnji koeficient v tabeli
mora biti neničelen.
Pomembno: Pri tej nalogi poskrbite, da bo tabela koeficientov lastnost. Torej uporabite dekorator:
@property
def koef(self):
# vrni vrednost
Če ne boste pravilno uporabili dekoratorja, boste dobili takole izjemo:
AttributeError: type object 'Polinom' has no attribute 'koef'
Podan imate osnutek razreda s konstruktorjem __init__(self, koef_pol),
ki priredi vrednost spremenljivke koef_pol lastnosti koef objekta.
Če kasneje spremenimo seznam, ki smo ga kot argument podali
konstruktorju, se koeficienti polinoma ne bodo spremenili.
class Polinom:
def __init__(self, koef_pol):
# Znebimo se vseh ničelnih vodilnih koeficientov polinoma:
zadnji = len(koef_pol) # vodilne nicle so kvecjemu zadaj
while zadnji > 0 and koef_pol[zadnji - 1] == 0:
zadnji -= 1
self._koef = koef_pol[:zadnji] # Rezina naredi kopijo seznama.
Sestavite lastnost koef kot zgoraj,
ki bo vrnila koeficiente polinoma tako, da jih kasneje ne bo mogoče
po pomoti spremeniti. Prav tako naj se koeficientov polinoma
kasneje ne sme spremnijati (polinom torej ustvarimo ob inicializaciji!)
>>> p = Polinom([1, 2, 3])
>>> l = p.koef
>>> l.append(4)
>>> p.koef
[1, 2, 3]
>>> l
[1, 2, 3, 4]
Naloga Bančni račun je nadgradnja naloge Bitni cekini iz sklopa Uvod v OOP.
Če ste že rešili nalogo Bitni cekini, jo uporabite kot osnovo za reševanje te naloge.
Če je še niste in imate z OOP še težave, vam priporočam, da jo rešite za vajo preden
se lotite te naloge.
Razred BancniRacun bo poleg podatka o stanju vseboval tudi podatek o lastniku računa
in bo implementiran z uporabo lastnosti (@property). Metode __str__, dvig in polog
naj do vrednosti dostopajo preko lastnosti (metod z oznako @property oziroma @nekaj.setter).
Sestavite razred BancniRacun s konstruktorjem __init__(self, stranka, začetno_stanje),
ki sprejme ime lastnika in začetno stanje na računu.
Lastnost, v katerega shranite lastnika, naj bo lastnik in naj se naknadno ne da
spreminjati.
Objekti tipa BancniRacun naj imajo tudi lastnost stanje, ki mora biti vedno
nenegativno decimalno število.
Parameter konstruktorja začetno_stanje naj bo neobvezen in v primeru, ko ni podan,
naj bo začetno stanje enako nič.
Sestavite metodo __str__(self), ki predstavi stanje na računu v obliki:
'Lastnik: <ime_lastnika>, stanje: <stanje_na_racunu>'
Primer:
>>> racun = BancniRacun("Marko", 6)
>>> print(racun)
Lastnik: Marko, stanje: 6
Sestavite metodi dvig(self, koliko) in polog(self, koliko), ki
dvigneta oz. položita ustrezno količino bitnih cekinov na račun.
Predpostavimo, da bo vrednost argumenta koliko vedno nenegativno
celo število (ni potrebno preverjati).
Pri metodi dvig upoštevajte, da stanje na računu ne sme biti negativno.
V takšnem primeru se dvig ne sme izvesti.
Metoda dvig naj vrne True, če je dvig uspel in False, če ni.
Metoda polog naj spremeni stanje in vrne stanje na računu po pologu.
Sestavite funkcijo prenesi(racun1, racun2, koliko), ki iz računa racun1
prenese koliko cekinov na račun racun2. Funkcija prenesi naj ne bo
znotraj razreda BancniRacun, saj ni objektna metoda, ampak je čisto običajna
funkcija. Spremenljivki racun1 in racun2 sta seveda objekta tipa
BancniRacun, kar ni potrebno preverjati!
Če na računu racun1 ni dovolj denarja, se transakcija ne sme
izvršiti, torej mora stanje na obeh računih ostati nespremenjeno.
Funkcija naj vrne uspešnost transakcije (True, če je transakcija uspela,
in False, če ni).
Sestavimo razred KvPol, ki ga bomo uporabili za predstavitev kvadratnih
polinomov, torej za "zadeve" oblike .
Pri tem dopuščamo, da so koeficienti lahko 0.
Za dostop do koeficientov pa bomo imeli tri lastnosti, ki jih bomo
poimenovali koef_a, koef_b, koef_c.
Polinom bomo ustvarili s klicem KvPol(2, -3, 10)
V razredu naj bosta še osnovni metodi za prikaz polinoma v obliki niza, ki se obnašata kot kaže zgled (ni najlepše, a to ni najpomembnejši del vaje)
>>> kv = KvPol(3, -3, 10)
>>> kv.koef_a
3
>>> kv.koef_a = 2
>>> repr(kv)
'KvPol(2, -3, 10)'
>>> str(kv)
2x**2 + -3x + 10
Namig: koeficiente lahko hranite kar v tabeli, a ta naj bo "privatna" (označena s _ na začetku imena).
Razred KvPol dopolni z metodo vrednost, ki izračuna vrednost
polinoma za dani x.
>>> pol1 = KvPol(2, 1, 3)
>>> pol1.vrednost(0)
3
>>> pol1.vrednost(1)
6
Jože goji zajce. V zadnjih letih so se tako namnožili, da si Jože enostavno ne more več zapomniti vseh. Zato potrebuje primeren informacijski sistem. V pomoč mu sestavite razred, ki bo vseboval vse potrebne podatke o vsakem zajcu.
Sestavite razred Zajec s konstruktorjem __init__(self, teza, starost), ki
predstavlja zajca z dano težo in starostjo. Lastnosti teza in starost naj
bodo definirane kot property, saj zajci z negativno težo in starostjo ne
obstajajo. Takšnim zajcom nastavite težo oz. starost na 0 (in se
pretvarjajte, da obstajajo zajci brez teže).
Sestavite metodo nahrani(self, hrana), kjer je argument hrana teža hrane,
ki jo damo zajcu. Pri hranjenju se teža zajca poveča za 30 % teže hrane, ki
jo zajec poje. Zgled:
>>> z = Zajec(5, 2)
>>> z.nahrani(2)
>>> z.teza
5.6
Sestavite metodo __str__(self), ki vrne predstavitev razreda Zajec z
nizom oblike 'Zajec težak X kg, star Y let.'.
Primer:
>>> z = Zajec(5, 2)
>>> print(z)
'Zajec težak 5 kg, star 2 let.'
Opomba: Funkcija print na svojem argumentu pokliče metodo __str__ in
izpiše niz, ki ga ta metoda vrne. Metoda __str__ običajno vrne razumljiv
opis objekta, ki naj bi ga razumeli tudi ne-programerji.
Sestavite še metodo __repr__, ki vrne predstavitev razreda Zajec kot niz
oblike 'Zajec(X, Y)', kjer je X teža, Y pa starost zajca.
Primer:
>>> z = Zajec(5, 2)
>>> z
Zajec(5, 2)
Opomba: Če v interaktivni konzoli pokličemo nek objekt, se izpiše niz, ki
ga vrne klic metode __repr__ na tem objektu. Priporočilo je, da je niz, ki
ga vrne metoda __repr__, veljavna programska koda v Pythonu, ki ustvari
identično kopijo objekta.
Sestavite metodo __lt__(self, drugi), ki dva zajca primerja med sabo.
Metoda naj vrne True, če je prvi zajec manjši od drugega in False sicer.
Manjši zajec je tisti, ki je lažji. Če pa imata zajca enako maso, je manjši tisti, ki je mlajši (tj. ima manjše število let).
>>> Zajec(5, 3) < Zajec(6, 2)
True
>>> Zajec(3, 1) < Zajec(2, 2)
False
>>> Zajec(4, 3) < Zajec(4, 2)
False
Sestavite funkcijo uredi(teze, starosti). Argumenta teze in starosti
sta enako dolga seznama števil, kjer -ti element predstavlja težo oz.
starost -tega zajca. Funkcija uredi naj ne bo znotraj razreda Zajec,
saj ni objektna metoda, ampak je čisto običajna funkcija.
Funkcija naj ustvari seznam ustreznih primerkov razreda Zajec, ga uredi po
velikosti glede na zgoraj opisano relacijo in ta seznam vrne kot rezultat.
Namig: metodo __lt__ ste že definirali, torej jo Python lahko uporablja
v svojih funkcijah.
>>> l = uredi([5, 4, 4], [3, 2, 3])
>>> for z in l:
... print(z)
...
Zajec težak 4 kg, star 2 let.
Zajec težak 4 kg, star 3 let.
Zajec težak 5 kg, star 3 let.
Koledar, ki ga trenutno uporabljamo v zahodnem svetu, se
imenuje gregorijanski koledar.
Pri tej nalogi bomo implementirali razred Datum, ki bo omogočal
predstavitev datumov v gregorijanskem koledarju in računanje z njimi.
Sestavite funkcijo je_prestopno(leto), ki preveri, ali je dano leto
prestopno (po gregorijanskem koledarju). Zgled:
>>> je_prestopno(2004)
True
>>> je_prestopno(1900)
False
Sestavite funkcijo stevilo_dni(leto), ki vrne število dni v danem letu.
Zgled:
>>> stevilo_dni(2015)
365
>>> stevilo_dni(2016)
366
Nasvet: Uporabite funkcijo je_prestopno.
Sestavite funkcijo dolzine_mesecev(leto), ki vrne seznam dolžine 12,
ki ima za elemente števila dni po posameznih mesecih v danem letu.
Zgled:
>>> dolzine_mesecev(2015)
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Sestavite metodo je_veljaven(d, m, l), ki preveri, ali d. m. l predstavlja
veljaven datum. Pri tem predpostavi, da so d, m in l zagotovo cela števila
Zgled:
>>> je_veljaven(8, 2, 1849)
True
>>> je_veljaven(5, 14, 2014)
False
Definirajte razred Datum, s katerim predstavimo datum.
Najprej sestavite konstruktor __init__(self, dan, mesec, leto).
Nastali objekt naj ima bralne lastnosti dan, mesec in leto.
Zgled:
>>> d = Datum(8, 2, 1849)
>>> d.dan
8
>>> d.mesec
2
>>> d.leto
1849
>>> d.dan = 12
Traceback (most recent call last):
...
AttributeError: can't set attribute
V primeru, da dan, mesec in leto ne predstavljajo veljavnega datuma, ustvari datum 1. 1. 2020
Sestavite metodo __str__(self), ki predstavi datum v obliki
'dan. mesec. leto'. Zgled:
>>> d = Datum(8, 2, 1849)
>>> print(d)
8. 2. 1849
Sestavite metodo spremeni(self, dan=None, mesec=None, leto=None), ki nastavi
datum na dan. mesec. leto in vrne True. Če je vrednost parametra None, uporabi
obstoječi dan (oz. mesec, leto).
Če datum dan. mesec. leto ni pravilen, naj metoda ne naredi nič
le vrne False.
>>> d = Datum(8, 2, 1849)
>>> print(d)
8. 2. 1849
>>> d.spremeni(30, 4, 1849)
Sestavite še metodo __repr__(self), ki vrne niz oblike
'Datum(dan, mesec, leto)'. Zgled:
>>> d = Datum(8, 2, 1849)
>>> d
Datum(8, 2, 1849)
Sestavite metodo dan_v_letu(self), ki izračuna, koliko dni je minilo
od začetka leta do danega datuma. Zgled:
>>> d = Datum(1, 11, 2014)
>>> d.dan_v_letu()
305
Nasvet: Ali si lahko kako pomagate s funkcijo dolzine_mesecev?
Sestavite metodo razlika(self, other), ki kot argument dobi še en
objekt razreda Datum in vrne število dni med datumoma. Dobra rešitev
deluje brez uporabe zanke po vseh letih med danima datuma (ima časovno
zahtevnost ). Zgled:
>>> datum1 = Datum(1, 11, 2014)
>>> datum2 = Datum(14, 10, 2014)
>>> datum1.razlika(datum2)
18
Namig: Najprej sestavite pomožno metodo dni_od_zacetka(self), ki izračuna,
koliko dni je minilo od "začetka štetja" (leto==0, mesec=1, dan=1).
Razliko v dnevih med self in other lahko nato preprosto izračunate z
metodo dni_od_zacetka.
Opomba: Gregorijanski koledar seveda ni bil v veljavi leta 0, ampak za potrebe računanja se lahko pretvarjamo, da ga je uporabljal tudi Julij Cezar.
Sestavite metodo dan_v_tednu(self), ki vrne številko dneva v tednu
(1 = ponedeljek, 2 = torek, …, 7 = nedelja). Lahko si pomagate z
Zellerjevim obrazcem.
Druga možnost je, da izračunate razliko med datumom self in nekim
fiksnim datumom, za katerega že poznate dan v tednu. Zgled:
>>> d = Datum(1, 11, 2014)
>>> d.dan_v_tednu()
6
Sestavite funkcijo datum_iz_dneva_v_letu(leto, dan), ki za parametra dobi
leto in zaporedno številko dneva v letu ter sestavi in vrne ustrezen datum.
Zgled:
>>> datum_iz_dneva_v_letu(2014, 305)
Datum(1, 11, 2014)
Sestavili bomo elektronski indeks študenta.
Ustvari razred Ocena, ki ima naslednje lastnosti: niz predmet,
trojico treh števil datum, predstavljeno z naborom oz. "tuplom", niz tip, ki je bodisi
"ustna" bodisi "pisna", stevilcna_ocena, ki je celo število od 1 do 10
vključno z njima in utez, ki je poljubno realno število od 0 do 1 vključno
z njima. Vse lastnosti naj se nastavijo v konstruktorju. Le datum in
stevilcna_ocena naj bosta nastavljivi lastnosti, ostale naj bodo zgolj bralne.
Ustreznost vseh tipov moraš preveriti!
Datum bo podan v obliki niza "dd. mm. llll", kjer sta za prvi januar 2000 ustrezna oba naslednja zapisa: "01. 01. 2000" in "1. 1. 2000". Leto mora biti celo število od 1919 do trenutnega leta vključno z njima. Če je datum pravilne oblike, ti ni treba preverjati, če res obstaja. Recimo "30. 02. 1970" je z vidika naloge ustrezen datum. Koda, ki preverja ustreznost datuma je že napisana, a ima nekaj napak, ki jih moraš popraviti. Ostalo kodo moraš napisati sam/a.
Lastnost utez pove, kolikšen delež k skupni oceni pri nekem predmetu
prispeva pisna in koliko ustna ocena. Lahko predpostaviš, da bo vsota uteži
za posamezni predmet vedno 1.
Neobvezno: dodaj še metodo __repr__, ki vrne oceno v zapisu, s katerim lahko ustvarimo
kopijo ocene (torej standardno delovanje). Bodi pozoren na zadnjo vrstico zgleda: prvi
trije argumenti znotraj oklepajev morajo biti nizi!
Zgled (zadnji dve vrstici prikazujeta delovanje metode __repr__):
>>> ocena = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.5)
>>> ocena.predmet
'Matematika 1'
>>> ocena.datum
(5, 6, 2007)
>>> Ocena('Numerične metode 1', (5, 7, 2005), 'pisna', 8, 0.5)
Traceback (most recent call last):
...
AttributeError: 'tuple' object has no attribute 'split'
During handling of the above exception, another exception occurred:
...
TypeError
>>> Ocena('Programiranje 3', '8. 7. 2011', 'ustna', 7, 13)
...
ValueError
>>>
>>> ocena
Ocena("Matematika 1", "5. 6. 2007", "pisna", 8, 0.5)
>>>
Znotraj razreda Ocena ustvari metodo popravi_oceno(self, nova_ocena),
ki lastnost stevilcna_ocena nastavi na vrednost nova_ocena, datum ocene
pa nastavi na današnji dan.
Zgled:
>>> ocena = Ocena('Algebra in diskretna matematika', '31. 1. 2013', 'pisna', 6, 0.8)
>>> ocena.stevilcna_ocena
6
>>> ocena.datum
(31, 1, 2013)
>>> ocena.popravi_oceno(9)
>>> ocena
Ocena(Algebra in diskretna matematika, 11. 5. 2020, pisna, 9, 0.8)
>>> ocena.stevilcna_ocena
9
>>> ocena.datum
(11, 5, 2020)
>>> ocena.tip
'pisna'
Ustvari razred Student, ki ima naslednje lastnosti: niz ime, spol, ki je
bodisi "Ž" bodisi "M", leto_rojstva, ki je celo število od 1800 do
trenutnega leta vključno z njima in tabelo tabela_ocen. Le zadnja naj bo
nastavljiva, vse ostale pa zgolj bralne. Preveriti moraš
ustreznost vseh tipov! Za podano tabelo ocen moraš preveriti, če je res tabela
in če so vsi njeni elementi tipa Ocena. Zadnje storiš takole:
isinstance(element_tabele, Ocena).
Zgled:
>>> tabela_ocen = [Ocena('Matematika 1', '05. 06. 2011', 'pisna', 8, 0.5),
Ocena('Matematika 1', '1. 7. 2011', 'ustna', 7, 0.5),
Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)]
>>> studentka = Student('Sabina Sabinovič', 'Ž', 1991, tabela_ocen)
>>> studentka.ime
'Sabina Sabinovič'
>>> studentka.tabela_ocen
[Ocena(Matematika 1, 5. 6. 2011, pisna, 8, 0.5), Ocena(Matematika 1, 1. 7. 2011, ustna, 7, 0.5), Ocena(Računalniški praktikum, 3. 2. 2011, pisna, 9, 1)]
>>> studentka.tabela_ocen[1].datum
(1, 7, 2011)
>>> studentka = Student('Sabina Sabinovič', 'ženska', 1991, tabela_ocen)
Traceback (most recent call last):
...
TypeError
>>> studentka = Student('Sabina Sabinovič', 'Ž', 1991, [10, 7])
Traceback (most recent call last):
...
TypeError
>>>
Znotraj razreda Student ustvari metodo dodaj_oceno(self, ocena), ki v
tabelo ocen študenta doda oceno. Metoda naj preveri, če je argument ocena
res tipa Ocena. Če ni, naj sproži napako.
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.5)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.5)
>>> student = Student('Simon Simonovič', 'M', 1987, [ocena1])
>>> student.dodaj_oceno(ocena2)
>>> student.tabela_ocen
[Ocena(Matematika 1, 5. 6. 2007, pisna, 8, 0.5), Ocena(Matematika 1, 1. 7. 2007, ustna, 7, 0.5)]
>>> student.dodaj_oceno(7)
Traceback (most recent call last):
...
TypeError
>>>
V razredu Student ustvari metodo ocene_v_mesecu(self, datum), ki za podani
mesec, zapisan v obliki "mm. llll" ali "m. llll" (kot v prvi podnalogi),
vrne tabelo vseh ocen, ki jih je študent
pridobil v danem mesecu. Če ocen v danem mesecu ni ali če je datum neveljaven,
naj metoda vrne prazen seznam. Lahko predpostaviš, da bo datum zapisan v
predpisani obliki.
Zgled:
>>> tabela_ocen = [Ocena('Matematika 1', '05. 06. 2011', 'pisna', 8, 0.5),
Ocena('Matematika 1', '30. 6. 2011', 'ustna', 7, 0.5),
Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)]
>>> študent = Student('Dunja Simonova', 'Ž', 1991, tabela_ocen)
>>> študent.ocene_v_mesecu('6. 2011')
[Ocena(Matematika 1, 5. 6. 2011, pisna, 8, 0.5), Ocena(Matematika 1, 30. 6. 2011, ustna, 7, 0.5)]
>>> študent.ocene_v_mesecu('07. 2011')
[]
>>>
Znotraj razreda Student ustvari metodo stevilo_ocen(self, tip), ki vrne
število vseh ocen zahtevanega tipa, ki jih je pridobil študent. Argument
tip naj ne bo obvezen. V tem primeru naj metoda vrne število vseh ocen, ne
glede na njihov tip.
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.5)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.5)
>>> student = Student('Aleksej Aleksandrovič', 'M', 1990, [ocena1, ocena2])
>>> student.stevilo_ocen()
2
>>> student.stevilo_ocen('pisna')
1
>>> student.stevilo_ocen('ustna')
1
>>>
Znotraj razreda Student sestavi metodo povprecna_ocena(self, tip),
ki vrne povprečje vseh študentovih ocen zahtevanega tipa, zaokroženo na štiri
decimalna mesta. Argument tip naj
ne bo obvezen in naj se obnaša enako kot v metodi stevilo_ocen.
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.4)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.6)
>>> ocena3 = Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)
>>> student = Student('Aleksej Aleksandrovič', 'M', 1990, [ocena1, ocena2, ocena3])
>>> student.povprecna_ocena()
8.0
>>> student.povprecna_ocena('pisna')
8.5
>>> student.povprecna_ocena('ustna')
7.0
>>>
V razredu Student ustvari metodo ocena_pri_predmetu(self, predmet),
ki izračuna uteženo oceno predmeta. Vsaka oceni je pripisana utež, ki pove,
kolikšen delež k skupni oceni prispeva. Predmet nima nujno natanko dveh oceh,
lahko pa predpostaviš, da je vsota vseh uteži ocen posameznega predmeta vedno 1.
Ker Python računa z binarnimi približki števil, lahko tudi tu dobiš kot rezultat periode, čeprav se z vidika formule ne bi smele pojaviti. Zato tudi tu rezultat zaokroži na štiri decimalna mesta.
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.3)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.7)
>>> ocena3 = Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)
>>> student = Student('Aleksej Aleksandrovič', 'M', 1990, [ocena1, ocena2, ocena3])
>>> student.ocena_pri_predmetu('Matematika 1')
7.3
>>>
Znotraj razreda Student sestavi metodo ocene_po_predmetih(self), ki vrne
slovar, čigar ključi so imena predmetov, vrednosti pa tabele ocen, ki jih je
študent pridobil pri ustreznem predmetu.
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.3)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.7)
>>> ocena3 = Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)
>>> student = Student('Aleksej Aleksandrovič', 'M', 1990, [ocena1, ocena2, ocena3])
>>> student.ocene_po_predmetih()
{'Matematika 1': [Ocena(Matematika 1, 5. 6. 2007, pisna, 8, 0.3), Ocena(Matematika 1, 1. 7. 2007, ustna, 7, 0.7)], 'Računalniški praktikum': [Ocena(Računalniški praktikum, 3. 2. 2011, pisna, 9, 1)]}
>>>
Znotraj razreda Student ustvari metodo neustrezni_predmeti(self), ki vrne
dve množici: v prvi množici so imena vseh predmetov, pri katerem je vsota uteži
vseh ocen manjša od 1, v drugi množici pa vsi predmeti, kjer je vsota uteži
vseh ocen večja od 1. Tip ocen nas ne zanima.
Del kode je že napisan in ima natanko eno napako. Odpravi jo in dopolni kodo!
Zgled:
>>> ocena1 = Ocena('Matematika 1', '05. 06. 2007', 'pisna', 8, 0.3)
>>> ocena2 = Ocena('Matematika 1', '1. 7. 2007', 'ustna', 7, 0.7)
>>> ocena3 = Ocena('Računalniški praktikum', '3. 2. 2011', 'pisna', 9, 1)
>>> ocena4 = Ocena('Statistika', '5. 11. 2008', 'ustna', 6, 0.5)
>>> ocena5 = Ocena('Optimizacija', '13. 8. 1999', 'ustna', 7, 0.7)
>>> ocena6 = Ocena('Optimizacija', '4. 7. 1999', 'pisna', 7, 0.5)
>>> študent = Student('Mirko', 'M', 1970, [ocena1, ocena2, ocena3, ocena4, ocena5, ocena6])
>>> študent.neustrezni_predmeti()
({'Statistika'}, {'Optimizacija'})
>>>
"Magične" metode
Prva in četrta podnaloga sta enaki kot v sklopu OOP I (Kvadratni polinomi). Če ste nalogo rešili v sklopu prejšnjih vaj, lahko rešitev uporabite pri tej nalogi, seveda pa ni prepovedano naloge rešiti ponovno za vajo.
Sestavimo razred KvPol, ki ga bomo uporabili za predstavitev kvadratnih
polinomov, torej za "zadeve" oblike .
Za dostop do koeficientov pa bomo imeli tri lastnosti, ki jih bomo
poimenovali koef_a, koef_b, koef_c.
Polinom bomo ustvarili s KvPol(2, -3, 10)
V razredu naj bosta še osnovni metodi za prikaz polinoma v obliki niza, ki se obnašata kot kaže zgled
>>> kv = KvPol(2, -3, 10)
>>> kv.koef_a = 3
>>> repr(kv)
'KvPol(3, -3, 10)'
>>> str(kv)
3x**2 + -3x + 10
Razred KvPol dopolni, tako, da bomo lahko seštevali polinome.
>>> pol1 = KvPol(2, 1, 3)
>>> pol2 = KvPol(1, -1, 2)
>>> pol1 + pol2
'KvPol(3, 0, 5)'
Namig: pomagajte si z metodo __add__, ki mora za dva vhodna polinoma vrniti
nov polinom, ki predstavlja njuno vsoto.
Razred KvPol dopolni tako, da bomo lahko polinome množili s faktorjem
>>> pol1 = KvPol(2, 1, 3)
>>> pol2 = KvPol(2, 1, 2)
>>> 2 * pol1
'KvPol(4, 2, 6)'
>>> pol2 * 1.5
'KvPol(3, 1.5, 3)'
Namig: pomagajte si z metodo __mul__, ki mora za vhodni polinom ter številski faktor
nov polinom, pomnožen za ta faktor.
Razred KvPol dopolni z metodo vrednost, ki izračuna vrednost
polinoma za dani x.
>>> pol1 = KvPol(2, 1, 3)
>>> pol1.vrednost(0)
3
>>> pol1.vrednost(1)
6
Kot pri nalogi Polinomi v sklopu Uvod v OOP
sestavite razred Polinom, s katerim predstavimo polinom v
spremenljivki .
Prvo podnalogo ste že reševali v sklopu OOP I kot Polinomi2 !
Polinom predstavimo s tabelo njegovih koeficientov,
kjer je -ti element tabele koeficient pri .
Na primer, polinom predstavimo s Polinom([7, 2, 0, 1]).
Razmislite, kaj predstavlja Polinom([]). Zadnji koeficient v tabeli
mora biti neničelen.
Pomembno: Pri tej nalogi poskrbite, da bo tabela koeficientov lastnost. Torej uporabite dekorator:
@property
def koef(self):
# vrni vrednost
Če ne boste pravilno uporabili dekoratorja, boste dobili takole izjemo:
AttributeError: type object 'Polinom' has no attribute 'koef'
Podan imate osnutek razreda s konstruktorjem __init__(self, koef_pol),
ki priredi vrednost spremenljivke koef_pol lastnosti koef objekta.
Če kasneje spremenimo seznam, ki smo ga kot argument podali
konstruktorju, se koeficienti polinoma ne bodo spremenili.
class Polinom:
def __init__(self, koef_pol):
# Znebimo se vseh ničelnih vodilnih koeficientov polinoma:
zadnji = len(koef_pol) # vodilne nicle so kvecjemu zadaj
while zadnji > 0 and koef_pol[zadnji - 1] == 0:
zadnji -= 1
self._koef = koef_pol[:zadnji] # Rezina naredi kopijo seznama.
Sestavite lastnost koef kot je opisano v navodilih naloge.
Pazite, da bo vrnila koeficiente polinoma tako, da jih kasneje ne bo mogoče
po pomoti spremeniti. Prav tako se koeficientov polinoma
kasneje ne sme spreminjati (polinom torej ustvarimo ob inicializaciji!)
>>> p = Polinom([1, 2, 3])
>>> l = p.koef
>>> l.append(4)
>>> p.koef
[1, 2, 3]
>>> l
[1, 2, 3, 4]
Sestavite metodo __eq__(self, other) za primerjanje polinomov. Zgled:
>>> Polinom([3, 2, 0, 1]) == Polinom([3, 2])
False
>>> Polinom([3, 2, 1, 0]) == Polinom([3, 2, 1])
True
Sestavite metodo __call__(self, x), ki izračuna in vrne vrednost
polinoma v x. Pri izračunu vrednosti uporabite Hornerjev algoritem.
Če definiramo metodo __call__, objekt postane "klicljiv" (tj. lahko
ga kličemo, kakor da bi bil funkcija). Zgled:
>>> p = Polinom([3, 2, 0, 1])
>>> p(1)
6
>>> p(-3)
-30
>>> p(0.725)
4.8310781249999994
Sestavite metodo __add__(self, other) za seštevanje polinomov. Metoda
naj sestavi in vrne nov objekt razreda Polinom, ki bo vsota polinomov,
ki sta operanda pri +
Zgled:
>>> Polinom([1, 0, 1]) + Polinom([4, 2])
Polinom([5, 2, 1])
Pozor: Pri seštevanju se lahko zgodi, da se nekateri koeficienti pokrajšajo: .
Sestavite metodo stopnja(self), ki vrne stopnjo polinoma.
Uporabite jo, da sestavite metodo __mul__(self, other) za množenje polinomov.
Metoda naj sestavi in vrne nov objekt razreda Polinom, ki bo produkt polinomov,
operandov pri *. Zgled:
>>> Polinom([1, 0, 1]) * Polinom([4, 2])
Polinom([4, 2, 4, 2])
Prvi dve nalogi sta iz Kompleksna števila I v OOP I.
Sestavljen je razred KompleksnoStevilo z metodama __init__(self, re, im),
lastnostma im in re ter __repr__(self).
Realni del kompleksnega števila je shranjen v spremenljivki
_re, imaginarni pa v _im. Metoda __repr__(self) predstavi kompleksno
število z nizom oblike KompleksnoStevilo(re, im).
Zgled:
>>> u = KompleksnoStevilo(3, 4)
>>> u
KompleksnoStevilo(3, 4)
Žal so se vrstice v kodi zamešale. uredi jih v pravilni vrstni red. Razen spreminanja vrstnega reda ne naredi nobene druge spremembe
Razredu dodaj metodo __str__(self), ki kompleksno stevilo predstavi z nizom
oblike npr. 3 + 4i
Pri tem bodi pozoren da:
◦ Če je realni ali imaginarni del števila enak 0, naj bo v nizu njegov člen
izpuščen (npr. namesto 2 + 0i pišemo samo 2).
◦ Če je imaginarni del števila enak 1, namesto 1i pišemo samo i. Če je
enak -1namesto -1i pišemo -i.
◦ Če je imaginarni del števila negativen, njegov predznak zamenja +. Torej,
namesto 2 + (-3)i pišemo kar 2 – 3i. Če je realni del enak 0 med predznakom
- in nadaljevanjem ni presledka. Torej namesto - 3i pišemo -3i.
Zgled:
>>> u = KompleksnoStevilo(3, 4)
>>> print(u)
3 + 4i
>>> v = KompleksnoStevilo(2, 0)
>>> print(v)
2
>>> w = KompleksnoStevilo(0, -4)
>>> print(w)
-4i
>>> w = KompleksnoStevilo(0, 1)
>>> print(w)
i
>>> y = KompleksnoStevilo(-2, -6)
>>> print(y)
-2 - 6i
>>> z = KompleksnoStevilo(0, 0)
>>> print(z)
0
Razširite razred tako, da podpira seštevanje dveh kompleksnih števil. Zgled:
>>> KompleksnoStevilo(3, -2) + KompleksnoStevilo(2, 1)
KompleksnoStevilo(5, -1)
Razširite razred tako, da podpira seštevanje kompleksnih števil z decimalnimi in celimi števili. Zgled:
>>> str(KompleksnoStevilo(3, -2) + KompleksnoStevilo(2, 1))
5 - i
>>> str(KompleksnoStevilo(3, 2) + 4.5)
7.5 + 2i
>>> str(5 + KompleksnoStevilo(3, -2))
8 - 2i
>>> str("bla" + KompleksnoStevilo(3, -2))
...TypeError('Kompleksna števila ne znamo seštevati s/z str')
Sestavite metodo __mul__(self, other), ki vrne produkt dveh kompleksnih števil.
Množenec na levi bo vedno tipa KompleksnoStevilo, množenec na desni pa je lahko
tudi navadno število tipa float ali int.
Zgled:
>>> KompleksnoStevilo(3, 4) * 2
KompleksnoStevilo(6, 8)
>>> KompleksnoStevilo(3, 4) * KompleksnoStevilo(2, -1)
KompleksnoStevilo(10, 2)
Omogočite, da lahko med sabo poljubno množimo kompleksna, cela in decimalna števila.
Zgled:
>>> d1 = KompleksnoStevilo(3, 4)
>>> d2 = KompleksnoStevilo(2, -1)
>>> d1 * d2
KompleksnoStevilo(10, 2)
>>> d1 * 3
KompleksnoStevilo(9, 12)
>>> 2.2 * d2
KompleksnoStevilo(4.4, -2.2)
>>> 7 * 3
21
Izven razreda KompleksnoStevilo sestavite funkcijo vsota_kompleksnih, ki
sprejme tabelo kompleksnih števil in vrne vsoto števil v tabeli.
>>> kompleksna = [KompleksnoStevilo(0, 0), KompleksnoStevilo(3, 4), KompleksnoStevilo(2, 2)]
>>> vsota_kompleksnih(kompleksna)
KompleksnoStevilo(5, 6)
Prve tri podnaloge ste že reševali pri OOPI pri nalogi Ulomki
Da ne bo težav pri testiranju, pri vseh podnalogah začnemo z
class Ulomek(Ulomek):
Seveda pa 1. podnalogo še vedno začnemo z
class Ulomek:
Sestavite razred Ulomek, s katerim predstavimo ulomek. Števec in
imenovalec sta celi števili, pri čemer je imenovalec vedno pozitiven.
Ulomki naj bodo vedno okrajšani.
Do števca lahko pridemo preko lastnosti st, do imenovalca pa preko lastnosti
im. Če poskusimo spremeniti števec ali imenovalec (torej lastnosti st ali im)
naj koda sproži napako z obvestilom "Obstoječega ulomka ne moremo spreminjati"
Zgled:
>>> u = Ulomek(5, -20)
>>> u.st
-1
>>> u.im
4
>>> u.st = 4
... Exception("Obstoječega ulomka ne moremo spreminjati")
Trenutna implementacija razreda Ulomek objekt Ulomek(5, 20) izpiše z nizom
oblike <__main__.Ulomek object at 0x000002CB41CDD2B0>, iz katerega ne moremo
razbrati za kateri ulomek gre. Kako naj se objekt našega razreda izpiše, lahko
sami določimo z metodama __str__ in __repr__. Kako metodi delujeta in
kakšna je razlika med njima si poglejte v
videu.
Sestavite metodo __str__(self), ki predstavi ulomek z nizom
oblike 'st/im'. Zgled:
>>> u = Ulomek(5, 20)
>>> print(u)
1/4
Sestavite še metodo __repr__(self), ki predstavi ulomek z nizom
oblike 'Ulomek(st, im)'. Zgled:
>>> u = Ulomek(5, 20)
>>> u
Ulomek(1, 4)
Sestavite metodo __eq__(self, other), ki vrne True če sta dva
ulomka enaka, in False sicer. Ko definirate to metodo, lahko ulomke
primerjate kar z operatorjem ==. Zgled:
>>> Ulomek(1, 3) == Ulomek(2, 3)
False
>>> Ulomek(2, 3) == Ulomek(10, 15)
True
Lahko prepodstavite, da je drugi parameter (desni operand pri ==) zagotovo objekt
iz razreda Ulomek.
Sestavite metodo __add__(self, other), ki vrne vsoto dveh ulomkov.
Ko definirate to metodo, lahko ulomke seštevate kar z operatorjem +.
Na primer:
>>> Ulomek(1, 6) + Ulomek(1, 4)
Ulomek(5, 12)
Lahko prepodstavite, da je drugi parameter (operand pri +) zagotovo objekt iz razreda
Ulomek.
Sestavite metodo __sub__(self, other), ki vrne razliko dveh ulomkov.
Ko definirate to metodo, lahko ulomke odštevate kar z operatorjem -.
Na primer:
>>> Ulomek(1, 4) - Ulomek(1, 6)
Ulomek(1, 12)
Lahko prepodstavite, da je drugi parameter (desni operand pri -) zagotovo objekt
iz razreda Ulomek.
Sestavite metodo __mul__(self, other), ki vrne zmnožek dveh ulomkov.
Ko definirate to metodo, lahko ulomke množite kar z operatorjem *.
Na primer:
>>> Ulomek(1, 3) * Ulomek(1, 2)
Ulomek(1, 6)
Lahko prepodstavite, da je drugi parameter (desni operand pri *) zagotovo objekt
iz razreda Ulomek.
Sestavite metodo __truediv__(self, other), ki vrne kvocient dveh
ulomkov. Ko definirate to metodo, lahko ulomke delite kar z operatorjem
/. Na primer:
>>> Ulomek(1, 6) / Ulomek(1, 4)
Ulomek(2, 3)
(Videli smo nekaj posebnih metod, seznam preostalih pa si lahko pogledaš npr. tukaj.)
Izven razreda Ulomek definirajte funkcijo priblizek(n), ki vrne
vsoto
Funkcija naj uporablja razred Ulomek. Zgled:
>>> priblizek(5)
Ulomek(163, 60)
Ali je izračunana vrednost blizu števila ?
Popravite razred Pes iz sklopa Uvod v OOP.
Podan je razred Pes s konstruktorjem __init__(self, ime_p, starost_p, visina_p).
Opremite ga z lastnostmi ime, starost in visina in ga popravite tako,
da bosta starost in višina vedno pozitivni števili:
če uporabnik vnese število manjše od 0, sprožite napako vrste ValueError.
Pozor: Enaka napaka naj se zgodi, če poskusimo ustvariti psa z nesmiselnimi podatki.
Razred Pes dopolnite tako, da bodo v zavetišču lažje našli potencialne
podvojene vnose v bazi. Sestavite metodo __eq__(self, other), ki bo vrnila
True, če imata psa enaki imeni, starosti in višini, sicer pa False.
Ta metoda se izvede, če uporabimo operator primerjanja (glej zgled).
Podvojen vnos:
>>> p1 = Pes('Rex', 5, 60)
>>> p2 = Pes('Rex', 5, 60)
>>> p1 == p2
True
Dva različna vnosa:
>>> p1 = Pes('Rex', 5, 60)
>>> p2 = Pes('Fifi', 4, 60)
>>> p1 == p2
False
Kot je dobro znano iz elektrotehnike, nadomestni upor dveh zaporedno vezanih upornikov izračunamo po formuli , nadomestni upor dveh vzporedno vezanih upornikov pa je .
Sestavi tabelo slovarjev nadomestni_upor_test, ki ti bo pomagala pri reševanju
naslednje podnaloge. Vsak posamezni slovar naj bo zastavljen tako
kot kaže naslednji primer:
{"R1": 0, "R2": 0, "vezava": 'Z', "rezultat": 0}
Razmisli, katere robne primere potrebuješ (pri tem si pomagaj z opisom naslednje podnaloge).
Napišite funkcijo nadomestni_upor(r1, r2, tip_vezave), ki kot argumenta dobi
dve števili r1 in r2 (tj. upor obeh upornikov) in tip vezave tip_vezave,
ki je bodisi znak 'V' bodisi znak 'Z'. Funkcija naj vrne nadomestni
upor vezja. Ta naj bo zaokrožen na tri decimalke.
Pozor: nekateri uporniki so vezani kratkostično in imajo upor 0.
(Upor dveh vzporedno vezanih upornikov, od katerih ima vsaj en upor 0, je 0.)
>>> nadomestni_upor(3, 5, 'Z')
8
>>> nadomestni_upor(3, 0, 'V')
0
>>> nadomestni_upor(3, 5, 'V')
1.875
Pri tej nalogi ti Tomo ne bo povedal kaj je narobe - pomagaj si s testi iz prve naloge.
Sestavite funkcijo upor_vezja(niz), ki izračuna nadomestni upor vezja.
Vezje je podano kot niz v "RPN notaciji": operandoma (tj. vrednosti dveh
uporov) sledi operator (tj. način vezave, 'V' ali 'Z').
Analizirajmo vezje '3 4 1 Z Z 0 V 3 2 Z V':
Niz '4 1 Z' tako pomeni, da sta zaporedno vezana upornika z upornostma
4 in 1 (ki ju lahko nadomestimo z enim upornikom z upornostjo 5). Torej je
enako, če bi imeli '3 5 Z 0 V 3 2 Z V'. Upora 3 in 5 sta spet zaporedno
vezana, torej dobimo vezje '8 0 V 3 2 Z V'.
V tem novem vezju niz '8 0 V' pomeni, da sta vzporedno vezana upornika z
upornostima 8 in 0. Vzporedna vezava, ki vsebuje kratkostični upornik, je
kratkostična, zato je 0 nadomestni upor vezja '8 0 V'. Skratka, dobimo
vezje '0 3 2 Z V'.
Niz '3 2 Z' pomeni, da sta zaporedno vezana upornika z upornostima 3 in 2
(in torej z nadomestno upornostjo 5). Če upoštevamo še to, potem dobimo
vezje '0 5 V', kar na koncu da rezultat 0.
>>> upor_vezja('3 5 Z 0 V 3 2 Z V')
0
Predpostavite, da v nizu niz nastopajo (poleg znakov 'V', 'Z'
in ' ') le nenegativna cela števila. Rezultat zaokroži na tri decimalke.
Napišite še funkcijo sestavi_racun(niz), ki namesto da izračuna
nadomestni upor vezja sestavi račun, ki ga je potrebno izračunati,
da dobimo nadomestni upor vezja.
>>> sestavi_racun('3 5 V 0 Z 3 2 V Z')
'(((1/3 + 1/5)^-1 + 0) + (1/3 + 1/2)^-1)'
>>> sestavi_racun('3 5 Z 0 V')
'0'
Namig: Ali lahko nalogo rešite tako, da malenkost predelate rešitev prejšnje naloge?
Stari električarski mački si račun poenostavijo na sledeč način: če je upor več kot 10-krat večji kot upor , potem za nadomestni upor zaporedne vezave upornikov in vzamejo kar , kot nadomestni upor vzporedne vezave pa kar upor . Seveda pa pravilno razumejo vezavo, če je kakšen upor enak 0.
Sestavite funkcijo stari_macki(niz), ki bo nadomestni upor vezja
izračunala po "metodi starih mačkov". Rezultat zaokrožite na tri decimalke.
>>> stari_macki('2 30 Z 20 V 3 2 Z V')
3.529
Polinome predstavimo s tabelo koeficientov, pri čemer element z indeksom predstavlja koeficient ob (med drugim torej prazna tabela predstavlja ničelni polinom).
Napišite funkcijo odstrani_odvecne_nicle(koeficienti), ki vrne tabelo
koeficienti, v katerem na koncu odstrani odvečne ničle.
Namreč polinom 2x + 3 bi lahko prestavili kot [3, 2] ali
pa [3, 2, 0] (torej 0 x^2 + 2x + 3) ali pa [3, 2, 0, 0, 0, 0].
>>> odstrani_odvecne_nicle([0, 1, 2])
[0, 1, 2]
>>> odstrani_odvecne_nicle([2, 1, 0])
[2, 1]
>>> odstrani_odvecne_nicle([0, 0, 0, 0, 0, 0])
[]
Napišite funkcijo odvod_polinoma(polinom, n), ki za dani polinom vrne
njegov n-ti odvod. Privzeta vrednost za n naj bo 1.
>>> odvod_polinoma([1, 2, 3])
[2, 6],
>>> odvod_polinoma([4, -1, 2, 0, 1], n=2)
[4, 0, 12],
>>> odvod_polinoma([1])
[]
Napišite funkcijo vsota_polinomov(polinom1, polinom2), ki vrne vsoto danih
polinomov.
>>> vsota_polinomov([1, 2, 3], [5, 6, 7, 8])
[6, 8, 10, 8]
>>> vsota_polinomov([1, 2, 3], [-1, -2, -3])
[]
Gibanje kolesarja na dirki podamo s tabelo časov (v minutah), ki povedo, koliko časa je kolesar porabil za posamezno etapo. Dolžina tabele pove, koliko etap je kolesar prevozil.
Napiši funkcijo statistika(casi), ki vrne par števil: število etap,
ki jih je kolesar prevozil, in skupen čas. Primer:
>>> statistika([14, 9, 23])
(3, 46)
V spremenljivki dirka je zapisana tabela tabel etapnih časov
kolesarjev. Napiši funkcijo zmagovalec(dirka), ki vrne par: število
etap, in indeks zmagovalca. Pozor: nekateri kolesarji pred zaključkom
dirke odstopijo, zato ne prevozijo vseh etap.
>>> dirka([[2, 1], [1, 2, 3], [6, 3, 1]])
(3, 1)
Prepdostavite lahko, da je dirko uspešno zaključil vsaj en tekmovalec ter da na koncu rezultat ni bil izenačen.
Dani sta dve (enako dolgi) tabeli časov po etapah. Funkcija
primerjaj(prvi, drugi) naj vrne trojico števil
(hitrejsi_prvi, enako_hitra, hitrejsi_drugi), kjer
hitrejsi_prvi pove, v koliko etapah je bil hitrejši
prvi tekmovalec,enako_hitra pove, v koliko etapah sta bila oba tekmovalca
enako hitra,hitrejsi_drugi pove, v koliko etapah je bil hitrejši
drugi tekmovalec.Na primer:
>>> primerjaj([3, 7, 4, 3], [5, 6, 3, 2])
(1, 0, 3)
Sestavite funkcijo idealni_cas(dirka), ki za tabelo tabel časov
dirka pove, koliko časa bi za celotno dirko potreboval idealni kolesar,
torej tak, ki bi posamezno etapo prevozil tako hitro kot zmagovalec te
etape.
>>> idealni_cas([[2, 1], [1, 2, 3], [6, 3, 1]])
3
Box blur je eden od filtrov, katerih učinek je zameglitev slike. Takšna orodja najdemo v programih za obdelavo slik, kot so npr. Photoshop, GIMP in Inkscape.
V našem primeru bomo imeli opraviti le s sivinskimi slikami. Slika bo
podana kot matrika. Vsak element matrike bo število med 0.0 (črna)
in 1.0 (bela). To število predstavlja barvo pripadajočega piksla.
Primer take sivinske slikice je naslednja matrika:
slika = [
[1.00, 0.72, 0.56, 0.45],
[0.92, 0.64, 0.48, 0.32],
[0.80, 0.57, 0.42, 0.25],
[0.73, 0.49, 0.35, 0.21]
]
Napišite funkcijo povprecna(mat, r, c), ki kot argument dobi
matriko mat, kot je opisana zgoraj ter celi števili r in c.
Funkcija naj izračuna in vrne povprečno vrednost tistih elementov
matrike, katerih številka vrstice se kvečjemu za 1 razlikuje od r,
številka stolpca pa se kvečjemu za 1 razlikuje od c. Zgled (slika
je matrika, kot je definirana zgoraj):
>>> povprecna(slika, 1, 2)
0.49
>>> povprecna(slika, 3, 0)
0.6475
Napišite funkcijo box_blur(mat), ki sestavi in vrne novo sliko, ki
jo dobi tako, da na sliki mat uporabi učinek box blur. Vrne naj
torej enako veliko matriko, katere element v -ti vrstici in -tem
stolpcu ima vrednost povprecna(mat, i, j).
Zgled (matrika slika naj bo enaka kot zgoraj):
>>> box_blur(slika)
[[0.82, 0.72, 0.5283333333333333, 0.4525],
[0.775, 0.6788888888888889, 0.49, 0.41333333333333333],
[0.6916666666666668, 0.6, 0.41444444444444445, 0.3383333333333333],
[0.6475, 0.56, 0.38166666666666665, 0.3075]]
Napišite še funkcijo box_blur_2(mat), ki naj deluje podobno kot
funkcija box_blur, le da ničesar ne vrača, pač pa spremeni matriko
mat, ki naj na koncu hrani rezultat uporabe filtra box blur.
Zgled (slika naj bo enaka kot zgoraj):
>>> box_blur_2(slika)
>>> slika
[[0.82, 0.72, 0.5283333333333333, 0.4525],
[0.775, 0.6788888888888889, 0.49, 0.41333333333333333],
[0.6916666666666668, 0.6, 0.41444444444444445, 0.3383333333333333],
[0.6475, 0.56, 0.38166666666666665, 0.3075]]
Namig: Kaj že naredi tabela1[:] = tabela2 ali tabela1 = tabela2[:]?
Jure se je odločil, da se bo udeležil kolesarskega maratona, zato je pričel
z dvomesečnim treningom. Treniral je vsak dan natanko eno uro in si dnevno
število prevoženih kilometrov zapisoval v enodimenzionalno tabelo realnih
števil. Pri tem je Jure opazil, da se njegova kondicija v glavnem izboljšuje,
saj lahko skoraj vsak dan prevozi nekoliko več kilometrov. Kljub vsem
prizadevanjem pa trening ni vedno pokazal želenih rezultatov, saj zaradi
utrujenosti mišic Jure ni uspel vedno povečati prevožene razdalje.
Pomagaj Juretu napisati funkcijo stagnacija, s pomočjo katere bo lahko
analiziral svoje nazadovanje (stagnacijo) v svojem treningu. Funkcija
stagnacija naj vrne število dni stagnacije.
Primeri:
stagnacija([26.5,27.1,27.3,27.9,26.8,26.5,27.2])
stagnacija([27.5,27.9,27.2,27.6,28.3,27.7,27.7,28.4,28.5])
Prva funkcija vrne vrednost 2, ker je prišlo 5. in 6. dan do
nazadovanja.
Druga funkcija vrne vrednost 3, ker je prišlo3., 6. in 7. dan do
nazadovanja.
Miha sledi Juretovemu postopku. Pri pogovorih ob pivu pravi, da njemu vedno uspe, da nikoli ne nazaduje, torej da vedno naslednji dan prevoz vsaj toliko kot prejšnji dan. Jure mu ne verjame in zato se dogovorita, da bo Miha naslednji dan prinesel zapiske svojega treninga.
Miha je seveda s pomočjo tvojega programa iz prejšnje naloge ugotovil, da
se je prejšnji dan preveč bahal in da dejansko tudi on določeno dni nazaduje.
Zato se odloči, da bo malo "popravil" svoj dnevnik.
Pomagaj mu, in sestavi funkcijo popravki(razdalje), ki na podlagi tabele
razdalj vrne novo tabelo (z istimi podatki), a v takem vrstnem redu,
da bi funkcija stagnacija na tej popravljeni tabeli vrnila 0!
Primeri:
>>>popravki([26.5,27.1,27.3,27.9,26.8,26.5,27.2])
[26.5, 26.5, 26.8, 27.1, 27.2, 27.3, 27.9]
>>>popravki([27.5,27.9,27.2,27.6,28.3,27.7,27.7,28.4,28.5])
[27.2, 27.5, 27.6, 27.7, 27.7, 27.9, 28.3, 28.4, 28.5]
Sestavite funkcijo filtriraj, ki sprejme dva niza in vrne nov niz sestavljen
zgolj iz znakov prvega niza, ki so hkrati tudi v drugem nizu, preostale znake
pa zamenja z _
Velikost črk je nepomembna.
>>> filtriraj("Ne gremo še domov", "ngm")
"N__g__m_______m__"
Sestavite funkcijo pretvori, ki sprejme niz in bazo ter vrne podano število
v desetiškem zapisu. Ko zmanjka števil si znaki sledijo po angleški abecedi
0123456789ABC.... Primer vrstnega reda lahko najdete v
string.ascii_uppercase. Lahko predpostavite, da bo baza vedno med 2 in 36.
>>> pretvori("10001", 2)
17
>>> pretvori("2ACBD04", 36)
4978911892
Sestavite funkcijo izbrisi_podvojene, ki sprejme niz in odstrani vse
zaporedno enake znake, kjer velikost črk ni pomembna. Če se po izbrisu pojavijo
nove podvojitve, naj jih funkcija ne izbriše.
>>> izbrisi_podvojene("aaab")
"b"
>>> izbrisi_podvojene("abaab")
"abb"
Sestavite funkcijo vsak_k_ti, ki sprejme niz in parameter k ter vrne nov
niz, kjer iz vhodnega niza vzame vsak k-ti znak. Za nesmiselne parametre
naj funkcija vrne prazen niz
>>> vsak_k_ti("abcdefghijk", 3)
"adgj"
>>> vsak_k_ti("abcdefghijk", 0)
""
Sestavitev funkcijo zaporedje, ki sprejme niz in vrne nov niz sestavljen iz
znakov na indeksih 0, 1, 3, 6, 10, ...
Namig: Ali razlike med indeksi sledijo kakemu preprostemu zaporedju?
>>> zaporedje("0123456789X")
"0136X"
Pri teh nalogah ti bo prav prišla rekurzija. Seveda se da stvari rešiti tudi brez nje, a uradne rešitve jo uporabljajo!
Sestavite funkcijo preberi_celo_stevilo, ki s standardnega vhoda prebere
celo število. Funkcija naj od uporabnika zahteva vnos, dokler le-ta
ne vnese veljavnega celega števila, in vrne prvo veljavno celo število.
>>> preberi_celo_stevilo()
> Vnesi celo število: sto
Žal "sto" ni celo število, poskusi ponovno!
> Vnesi celo število: trinajst
Žal "trinajst" ni celo število, poskusi ponovno!
> Vnesi celo število: 10
10
S pomočjo prejšnje funkcije sestavi funkcijo ugibaj, ki sprejme pravilni
odgovor in uporabnika sprašuje po številki, dokler le-ta ne ugane pravilne.
Funkcija uporabnika obvesti, ali je njegov odgovor pravilen, ali pa je ciljno
število večje/manjše. Funkcija naj ne vrača ničesar (None).
>>> ugibaj(20)
> Vnesi celo število: a
Žal "a" ni število, poskusi ponovno!
> Vnesi celo število: b
Žal "b" ni število, poskusi ponovno!
> Vnesi celo število: 14
Moje število je večje!
> Vnesi celo število: 30
Moje število je manjše!
> Vnesi celo število: x
Žal "x" ni število, poskusi ponovno!
> Vnesi celo število: 20
BRAVO! Res sem si zamislil število 20!
Sestavite funkcijo racunalnik_ugiba(spodnji, zgornji), ki z metodo bisekcije
ugiba število med spodnji in zgornji, ki si ga je uporabnik zamislil.
To pomeni, da računalnik ugiba število, ki je na sredini med spodnji in
zgornji, nato pa glede na odgovor uporabnika primerno premakne interval
ugibanja. Če je veljavno le še eno število, tj., zgornja meja je enaka spodnji,
naj računalnik tako proslavi zmago. Funkcija naj ne vrača ničesar (None).
>>> racunalnik_ugiba(1,10)
Ali je tvoje število Enako/Večje/Manjše od 5?
E/V/M> 42
Ali lahko daš normalen odgovor?
Ali je tvoje število Enako/Večje/Manjše od 5?
E/V/M> banana
Ali lahko daš normalen odgovor?
Ali je tvoje število Enako/Večje/Manjše od 5?
E/V/M> M
Ali je tvoje število Enako/Večje/Manjše od 2?
E/V/M> V
Ali je tvoje število Enako/Večje/Manjše od 3?
E/V/M> V
Juhu, uganil sem! Zamislil si si število 4!
>>> racunalnik_ugiba(1,20)
Ali je tvoje število Enako/Večje/Manjše od 10?
E/V/M> v
Ali je tvoje število Enako/Večje/Manjše od 15?
E/V/M> m
Ali je tvoje število Enako/Večje/Manjše od 12?
E/V/M> e
Juhu, uganil sem! Zamislil si si število 12!
Z metodo Monte Carlo lahko računamo tudi ploščine. Pri tem gre v grobem za to, da naključno izbiramo točke na nekem pravokotniku in štejemo, koliko točk je takih, da "spadajo" k ploščini. Če razmerje med "zadetki" in vsemi točkami pomnožimo s ploščino pravokotnika, dobimo približek za ploščino območja.
Ploščino pod enim valom funkcije sinus (enaka je 2) lahko približno izračunamo tudi tako, da naključno izbiramo točke na pravokotniku [0, Pi] x [0, 1] in s Pi pomnožimo razmerje med točkami pod valom in vsemi točkami.
Sestavi funkcijo ploscina_val(n), ki izračuna ploščino vala funkcije
sin(x) po opisani metodi. Število naključnih točk
funkcija dobi kot parameter.
V tej nalogi si bomo ogledali osnove izpeljanih seznamov. Naloge bodo zato enake ali vsaj precej podobne nalogam, ki smo jih v preteklosti že reševali, a jih tokrat rešite z uporabo izpeljanih seznamov.
Včasih želimo ustvariti seznam (tabelo), ki ga lahko zapišemo s preprosto for zanko, na primer tabelo kvadratov celih števil med 1 in vključno 10.
Do sedaj smo to zapisali takole:
tabela = []
for i in range(1, 11):
tabela.append(i**2)
Znamo to napisati krajše?
Izpeljan seznam sestavimo podobno kot navaden seznam ([1, 4, 9, 16, 25, 36, 49, 64, 81, 100]), le da tokrat namesto konkretnih vrednosti v seznam vpišemo kar izraz, s katerim te vrednosti izračunamo.
tabela = [i**2 for i in range(1, 11)]
Kaj pa kompleksnejši izrazi? Lahko dodamo le kvadrate, ki so sodi?
V izpeljan seznam lahko dodamo tudi pogoj, pod katerim bomo to vrednost dodali v seznam. Na primer:
tabela = [i**2 for i in range(1, 11) if i**2 % 2 == 0]
Napiši funkcijo veckratniki(k, n), ki vrne seznam prvih n večkratnikov števila k,
kjer je .
Funkcija naj seznam ustvari s pomočjo izpeljanega seznama - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
For example:
>>> veckratniki(2, 5)
[2, 4, 6, 8, 10]
Napiši funkcijo kvadrati(stevila), ki ustvari nov seznam, ki vsebuje
kvadrate vrednosti iz seznama stevila.
Funkcija naj seznam ustvari s pomočjo izpeljanega seznama - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
For example:
>>> kvadrati([2, 1, 0, -1, -2, -1, 0, 1, 2])
[4, 1, 0, 1, 4, 1, 0, 1, 4]
>>> kvadrati([])
[]
Namig: Namesto, da gremo s for zanko čez range (for i in range(...)),
gremo kar čez podani seznam stevila.
Napiši funkcijo odstrani_negativne(stevila), ki ustvari nov seznam, ki vsebuje
le nenegativne vrednosti iz seznama stevila.
Funkcija naj seznam ustvari s pomočjo izpeljanega seznama - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
For example:
>>> odstrani_negativne([2, 1, 0, -1, -2, -1, 0, 1, 2])
[2, 1, 0, 0, 1, 2]
>>> odstrani_negativne([1, 2, 3, 4, 5, 6])
[1, 2, 3, 4, 5, 6]
>>> odstrani_negativne([-1, -2, -3, -4, -5, -6])
[]
>>> odstrani_negativne([])
[]
Napiši funkcijo povecaj_crke(nizi), ki ustvari nov seznam, ki vsebuje
neprazne nize iz seznama nizi, le da naj bodo ti spremenjeni v *velike tiskane črke.
Funkcija naj seznam ustvari s pomočjo izpeljanega seznama - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
For example:
>>> povecaj_crke(["Kokos", "kraVa", "MAČKA", "kričač"])
["KOKOS", "KRAVA", "MAČKA", "KRIČAČ"]
>>> povecaj_crke(["", " x", "", "", " "])
[" X", " "]
V tej nalogi bo že podana koda, zapisana s klasično for zanko. For zanko nadomestite z izpeljanim seznamom. Poleg pravilnosti testi preverjajo število vrstic v telesu funkcije. Telo funkcije naj bo zapisano v eni vrstici (v to kvoto ne sodijo prazne vrstice ter vrstice s komentarji in dokumentacijskimi nizi).
Ugotovi kaj dela funkcija in jo pretvori v izpeljani seznam.
import random
def funkcija1(n, a, b):
seznam = []
for _ in range(n):
seznam.append(random.randint(a, b))
return seznam
Ugotovi kaj dela funkcija in jo pretvori v izpeljani seznam.
def funkcija2(seznam, k):
nov_seznam = []
for el in seznam:
if el % k == 0:
nov_seznam.append(el)
return nov_seznam
Podobno kot izpeljane sezname lahko tvorimo tudi slovarje in množice.
Množico kvadratov naravnih števil od 1 do 5, na primer, ustvarimo tako:
{x**2 for x in range(1, 6)}, # to ustvari množico {1, 4, 9, 16, 25}
slovar, ki ima za ključ števke od 1 do 6, vrednosti pa so ključi deljeni z dva, če je ključ sod, sicer pa ključ pomnožen s 3 in povečan za 1 pa takole:
{x: x//2 if x%2==0 else 3*x+1 for x in range(1, 6)}
# dobljeni slovar je {1: 4, 2: 1, 3: 10, 4: 2, 5: 16, 6: 3}
Napiši funkcijo potence2(n), ki vrne množico potenc 2:
Funkcija naj množico ustvari s pomočjo izpeljane množice - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
Na primer:
>>> potence2(5)
{1, 2, 4, 8, 16, 32}
Napiši funkcijo mnozica_sodih(stevila), ki vrne množico sodih elementov
seznama stevila.
Funkcija naj množico ustvari s pomočjo izpeljane množice - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
Na primer:
>>> mnozica_sodih([1, 4, 5, 2, 7, -8, 5, 0, 101, 2, 1])
{4, 2, -8, 0}
Napiši funkcijo ustvari_slovar(seznam_parov), ki iz seznama parov oblike [(k_i, v_i)]
ustvari slovar, ki ima za ključe , za vrednosti pa .
Funkcija naj množico ustvari s pomočjo izpeljane množice - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
Na primer:
>>> ustvari_slovar([(1, "ena"), (2, "dve"), (3, "tri"), (11, "enajst")])
{1: "ena", 2: "dve", 3: "tri", 11: "enajst"}
Napiši funkcijo obrni_slovar(slovar), ki iz podanega slovarja ustvari nov seznam,
ki ima za ključe vrednosti starega slovarja, za vrednosti pa ključe starega slovarja.
Predpostaviš lahko, da se posamezna vrednost pojavi pri natanko enem ključu.
Funkcija naj množico ustvari s pomočjo izpeljane množice - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
Na primer:
>>> obrni_slovar({1: 3, 2: 1, 3: 4, 4: 2})
{3: 1, 1: 2, 4: 3, 2: 4}
Napiši funkcijo pomnozi(slovar, k), ki ustvari nov slovar, kjer so vrednosti
slovarja pomnožene s k. Vključeni naj bodo le ključi, pri katerih je vrednost
večja od 0.
Funkcija naj množico ustvari s pomočjo izpeljane množice - telo funkcije naj bo torej zapisano v eni vrstici. V telo funkcije se ne štejejo vrstični komentarji in dokumentacijski niz.
Na primer:
>>> pomnozi({'jajca': 4, 'moka': 500, 'mleko': 0}, 2)
{'jajca': 8, 'moka': 1000}
Včasih pri reševanju programerskih problemov potrebujemo preproste funkcije, ki jih lahko zapišemo z enim izrazom in jih želimo uporabiti le na enem mestu. Takrat ne želimo definirati nove funkcije s ključno besedo def, ampak namesto nje ustvarimo kar anonimno (lambda) funkcijo na mestu, kjer jo potrebujemo.
Tovrstne funkcije so zelo uporabne na primer kot ključ za sortiranje, iskanje najmanjšega/največjega elementa v tabeli, podajanje funkcije kot argument drugi funkciji...
Oglejmo si nekaj preprostejših primerov:
Lambda funkcija, ki argument x poveča za 1: lambda x: x + 1
Lambda funkcija, ki se šteje argumenta x in y: lambda x, y: x + y
Lambda funkcija, ki vrne "večji", če je x strogo večji od y, sicer pa "manjši":
lambda x, y: "večji" if x < y else "manjši"
Napiši funkcijo najkrajsa(besede), ki vrne najkrajšo besedo v seznamu besede.
Primer:
>>> najkrajsa(["banana", "krompir", "kisla repa", "kis"])
"kis"
Telo funkcije naj bo dolgo le eno vrstico (torej oblike return izraz_ki_resi_problem).
Namig: Uporabi funkcijo min(), ki sprejme seznam in opcijski argument key.
Kot ključ uporabite lambda funkcijo, ki bo določila vrednost posameznega elementa.
min(seznam, key=lambda x: nek_izraz)
V lambda funkciji zapišemo izraz, na podlagi katerega se bo izračunala vrednost
posameznega elementa seznama. To vrednost bo funkcija min uporabila kot ključ
na podlagi katerega izbere najmanjši element.
Napiši funkcijo uredi_po_uspesnosti(ekipe), ki podani seznam parov imen
košarkarskih ekip in njihov odstotek zmag uredi od najuspešnejše do najmanj
uspešne (torej padajoče). Funkcija naj vrne nov seznam, seznama ekipe naj
ne spreminja.
Primer:
>>> uredi_po_uspesnosti([("Jazz", 0.598), ("Grizzlies", 0.683), ("Mavericks", 0.634), ("Nuggets", 0.585), ("Warriors", 0.646), ("Suns", 0.780)])
[("Suns", 0.780), ("Grizzlies", 0.683), ("Warriors", 0.646), ("Mavericks", 0.634), ("Jazz", 0.598), ("Nuggets", 0.585)]
Telo funkcije naj bo dolgo le eno vrstico (torej oblike return izraz_ki_resi_problem).
Namig: Uporabi funkcijo sorted(), ki sprejme seznam in opcijska argumenta key in reverse.
Napiši funkcijo najbolj_raznolika(besede), ki vrne najbolj raznoliko besedo v seznamu besede.
Najbolj raznolika beseda je tista, ki ima največ različnih soglasnikov.
Primer:
>>> najbolj_raznolika(["banana", "krompir", "kisla repa", "kis"])
"kisla repa"
Telo funkcije naj bo dolgo le eno vrstico (torej oblike return izraz_ki_resi_problem).
Namig: Pomagaj si z množicami.
Matriko v Pythonu predstavimo s seznami seznamov, pri čemer predpostavimo, da ima matrika vsaj en element in da imajo vsi podseznami enako dolžino.
Naloge reši z uporabo izpeljanih seznamov.
Enako kot zanke lahko gnezdimo tudi izpeljane sezname. Tako bi na primer zanko,
ki ustvari seznam seznamov enic z n vrsticami in m stolpci
enice = []
for i in range(n):
vrstica = []
for j in range(m):
vrstica.append(1)
enice.append(vrstica)
prevedli v izraz:
enice = [[1 for j in range(m)] for i in range(n)]
Sestavite funkcijo diagonala(matrika), ki vrne seznam elementov na diagonali
podane matrike.
>>> diagonala([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
[1, 1, 1, 1]
Sestavite funkcijo vsota_elementov(matrika), ki vrne vsoto vseh elementov matrike.
>>> vsota_elementov([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
4
Sestavite funkcijo identiteta(n), ki vrne identično matriko dimenzij
n × n.
>>> identiteta(3)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
Sestavite funkcijo transponiraj, ki sestavi in vrne novo matriko in sicer
transponiranko dane matrike dimenzij n × m.
>>> transponiraj([[1, 2], [3, 4]])
[[1, 3], [2, 4]]
Sestavite funkcijo sestej, ki sprejme dve matriki in sestavi ter vrne novo
matriko, ki je vsota podanih matrik.
>>> sestej([[1, 0], [0, 1]], [[0, 2], [0, 0]])
[[1, 2], [0, 1]]
Sestavite funkcijo splosci(matrika), ki matriko po vrsticah splošči v vektor.
>>> splosci([[1, 0], [0, 1]])
[1, 0, 0, 1]
Naslednje naloge so podobne nalogam iz prejšnjih sklopov. Tokrat naloge rešite z uporabo novo pridoboljenih znanj - izpeljanih struktur in lambda funkcij.
Sestavite funkcijo stevilo_dolgih_vrstic(ime_datoteke, dolz), ki vrne
število vseh vrstic v datoteki z danim imenom, ki so dolge vsaj dolz znakov
(pri tem je dolz-ti lahko tudi znak "\n" za novo vrstico).
Sestavite funkcijo najdaljsa_vrstica(ime_datoteke), ki vrne najdaljšo
vrstico v datoteki z danim imenom. Če je takih vrstic več, vrni prvo!
Namig, uporabi funkcijo max.
Naloge v tem sklopu služijo spoznavanju z dedovanjem v objektno usmerjenem programiranju.
Za spoznavanje z dedovanjem si oglejmo preprost primer.
Napiši razred Zival, ki bo žival predstavil z imenom, višino in težo.
Razred naj vsebuje konstruktor, ki nastavi vrednosti lastnosti (property) ime,
visina, teza. Pri lastnostih naredi smiselne kontrole.
Razredu dodaj metodo predstavi_se, ki vrne predstavitveni niz živali kot
kaže primer:
>>> zival = Zival("Nana", 10, 0.5)
>>> print(zival.predstavi_se())
Sem Nana, merim 10 centimetrov in tehtam 0.5 kilogramov.
Sedaj ustvari razred Macka, ki predstavlja mačko. Ker velja, da je mačka
tudi žival in ima vse lastnosti živali - ime, višino in težo, lahko
razred Macka podeduje lastnosti in metode razreda Zival.
Če želimo, da razred Podrazred deduje iz razreda Razred, ga ustvarimo takole
class Podrazred(Razred):
V telo razreda zaenkrat napišimo samo ukaz pass.
Sestavi program, ki ustvari novo mačko v spremenljivki macka z imenom Tačka, višino 20 cm
in težo 5kg. Nato izpiši
njeno ime (macka.ime). Nato pokliči metodo predstavi_se() in izpiši vrnjeni niz.
Kot opaziš, se tudi pri mački nastavijo enake lastnosti kot pri živali, prav tako
pa nad mačkami prav tako lahko uporabljamo metode iz razreda živali, čeprav
jih nismo izrecno definirali. Kadar metoda v podrazredu ni definirana
(v tem primeru __init__ in predstavi_se), Python izvede metodo iz starševskega
razreda.
Pri prejšnji podnalogi smo ugotovili, kako nam dedovanje pomaga pri tem, da imajo tudi objekti podrazredov dostop do metod nadrazreda. Vendar pa ponavadi podrazredom želimo dodati še kakšno lastnost ali metodo, da razširimo oziroma prilagodimo funkcionalnost.
Definiraj razred Pes, ki bo prav tako kot Macka dedoval iz razreda
Zival. Objektom tipa pes bomo tokrat želeli dodati še lastnost pasma.
Sedaj moramo torej napisati konstruktor __init__, ki bo poleg imena,
teže in višine prejel še pasmo. Lastnost pasma torej nastavimo v konstruktorju,
kot smo tega navajeni že iz preteklih srečanj z OOP. Ker so ostale lastnosti enake
starševskemu razredu Zival, lahko za njihovo nastavitev poskrbi kar konstruktor
za žival.
Konstruktor starševskega razreda, ki sprejme argumente args, pokličemo takole:
def __init__(self, args):
super().__init__(args)
Podobno kot smo storili s konstruktorjem, lahko v podrazredu pokličemo tudi
druge metode nadrazreda. Napiši metodo predstavi_se(), ki bo predstavitev
iz starševskega razreda dopolnila s "pasjim" pozdravom in informacijo o
pasmi, kot kaže primer:
>>> pes = Pes("Reks", 100, 30, "nemški ovčar")
>>> print(pes.predstavi_se())
Hov! Sem Reks, merim 100 centimetrov in tehtam 30 kilogramov. Sem nemški ovčar.
Včasih pa bomo želeli metode starševskega razreda kar povoziti.
Napiši razred Lisica, ki bo sprejel enake argumente kot Zival - uporabi
konstruktor razreda Zival.
Definirajte metodo predstavi_se, ki vrne naključnega izmed nizov:
nizi = [
"Ring-ding-ding-ding-dingeringeding!",
"Wa-pa-pa-pa-pa-pa-pow!",
"Hatee-hatee-hatee-ho!",
"Joff-tchoff-tchoffo-tchoffo-tchoff!"]
Opomba: za tiste, ki ne veste, kako se oblaša lisica: Ylvis - The Fox :D
V knjižnici potrebujejo nov informacijski sistem. Pomagajte jim pripraviti ustrezne razrede za ustrezen prikaz podatkov.
Za začetek pripravite razred Gradivo, ki bo predstavljal knjižnično gradivo.
Napišite konstruktor, ki bo nastavil lastnosti naslov in avtor gradiva, podana kot argument.
Dodajte še metodo za izpis, ki bo delovala, kot kaže primer:
>>> gradivo = Gradivo("Naslov gradiva", "Ime Avtorja")
>>> gradivo.avtor
Ime Avtorja
>>> print(gradivo)
[Gradivo neznanega tipa] Ime Avtorja: Naslov Gradiva
Ker pa želi knjižnica natančneje definirati tip gradiva, poleg tega pa za različne
tipe gradiv hraniti različne lastnosti in jih izpisovati različno, bomo definirali
nekaj podrazredov. Kot vsaka dobra knjižnica, je tudi pri nas najpomembnejši
tip gradiva knjiga. Definirajte razred Knjiga, ki bo podrazred razreda
Gradivo (torej bo dedoval iz tega razreda, kot smo se naučili pri uvodni nalogi).
Poleg lastnosti naslov in avtor (uporabi naj kar konstruktor razreda Gradivo),
naj razred Knjiga hrani še podatek o številu strani v lastnosti st_strani.
Dodajte še metodo za izpis, ki bo pripravila izpis oblike:
[Knjiga] Ime Avtorja: Naslov knjige (100 strani)
Ker dandanes veliko ljudi raje gleda filme, kot pa bere, se je knjižnica odločila
izposojati tudi filme. Podobno razredu Knjiga definirajte tudi razred Film,
le da bo imel ta poleg naslova in avtorja še lastnosti trajanje in zvrst.
Film('Titanic', 'J. Cameron', 'drama', 194)
Metoda za izpis naj sestavi takšen izpis:
[Film] Ime Avtorja: Naslov filma (komedija; 100 minut)
[Film] J. Cameron: Titanic (drama; 194 minut)
Sedaj, ko imamo pripravljene različne tipe gradiva, ki jih naša knjižnica ponuja,
se lahko lotimo priprave krovnega razreda - razreda Knjiznica. Tako lahko
delovanje našega informacijskega sistema razširimo na večje število knjižnic.
Razred knjižnica naj ima lastnosti (@property) ime in gradiva, ki naj ju
ne bo mogoče spreminjati (če to želimo, naj se sproži napaka AttributeError).
Ob ustvarjanju nove knjižnice, bomo podali ime, seznam gradiv pa naj bo prazen.
Razredu knjižnica dodajte metodo dodaj_gradivo(self, gradivo), ki v seznam
gradiv pripne novo gradivo. Če podano gradivo ni podatkovnega tipa Gradivo
(oziroma njegovih podtipov), naj metoda sproži napako TypeError.
Za lažje delo razredu Knjiznica dodajmo še metodo __str__.
Ta naj sestavi takšen izpis:
V prvi vrstici naj se nahaja niz "Knjiznica <ime_knjiznice> ponuja naslednja gradiva:".
Sledi naj prazna vrstica, nato pa naj sledijo izpisi posameznih gradiv. Za boljšo
preglednost naj bodo ločeni z vrstico poljubnega števila znakov "-".
Primer izpisa:
Knjiznica RadiBeremo ponuja naslednja gradiva:
[Knjiga] Karl May: Vinetou I (555 strani)
---------------------------
[Knjiga] Douglas Adams: Štoparski vodnik po Galaksiji (169 strani)
---------------------------
[Film] Theodore Melfi: Hidden Figures (biografija; 127 minut)
---------------------------
[Film] Morten Tyldum: The Immitation Game (biografija; 114 minut)
---------------------------
[Gradivo neznanega tipa] Ian Goodfellow: Generative Adversarial Networks
Sedaj, ko smo ustvarili vse potrebne razrede in metode, je čas, da jih
uporabimo. Ustvarite novo knjižnico s poljubnim imenom. Dodajte ji vsaj
pet gradiv različnih tipov. Nato knjižnico izpišite (print).
Preverite, da so gradiva izpisana pravilno. V poročilu oddajte posnetek zaslona izpisa.
Za začetek napišite razred Tocka, ki predstavlja točko na ravnini. Predstavljena
naj bo s koordinatama x in y (naj bosta lastnosti - property in nimata metode setter),
ki sta podani konstruktorju.
Razredu dodajte še metodo __str__, ki točko predstavi z izpisom oblike (x, y) in
__repr__, ki točko predstavi z izpisom oblike Tocka(x, y)
Napišite metodo razdalja(self, druga), ki sprejme drugo točko in izračuna razdaljo
med dvema točkama.
Ustvarite točko tocka s koordinatama in in stestirajte, da deluje
pravilno. Izračunajte njeno razdaljo do koordinatnega izhodišča in jo shranite v
spremenljivko razdalja.
Primer:
>>> t = Tocka(0, 10)
>>> t
(0, 10)
>>> round(t.razdalja(Tocka(10, 10)))
10
Napišite razred Veckotnik, ki bo hranil tabelo točk v lastnosti tocke. Lastnost
naj ne omogoča nastavljanja. Za lažje delo z večkotniki preverite, če je zadnja
točka v seznamu enaka prvi - če ni, jo dodajte.
Razredu večkotnik dodajte metodi obseg in ploscina, ki izračunata
obseg in ploščino poljubnega večkotnika (lahko predpostavite, da nima samopresečišč).
Namig: pri računanju ploščine si pomagajte s formulo (shoelace formula) in poskrbite, da bo rezultat pozitiven.
Namig 2: pri računanju obsega si lahko pomagate z metodo za računanje razdalje med
točkami iz razreda Tocka.
Ustvarite večkotnik, določen s točkami , , , ,
, . V spremenljivko ob_nkot shranite njegov obseg, v pl_nkot
pa njegovo ploščino. Preverite, da je ploščina enaka 8,5, obseg pa približno enak 12,36.
Sestavite razred Trikotnik, ki naj bo izpeljan iz razreda Veckotnik (naj deduje iz njega),
Namesto tabele točk, želimo konstruktorju trikotnika podati kar tri oglišča:
__init__(self, a, b, c). Konstruktor naj jih sestavi v tabelo in posreduje
konstruktorju razreda Veckotnik.
Ustvarite nov trikotnik z oglišči , , in ga shranite
v spremenljivko trikotnik. Izračunajte obseg in ploščino, ter ju shranite
v spremenljivki ob_3kot in pl_3kot. Preverite, da je obseg približno 9,84,
ploščina pa 4.
Sedaj napišite še razred Pravokotnik, ki naj prav tako deduje iz razreda
Veckotnik. Pravokotnik želimo definirati s spodnjim levim ogliščem
(torej tistim, ki ima najmanjšo in koordinato) ter
širino in višino: __init__(self, ta, sirina, visina).
Konstruktor naj izračuna preostale točke in jih poda konstruktorju nadrazreda. Poleg tega naj si zapomni tudi višino in širino.
Ker poznamo višino in širino pravokotnika, lahko ploščino izračunamo učinkoviteje
kot za poljubni večkotnik. Dodajte metodo ploscina.
Ustvarite pravokotnik s točko , širino 3 in višino 2 in ga shranite
v spremenljivko pravokotnik. Preverite, da je ploščina enaka 6, obseg pa 10.
Preverite še, da bi splošen večkotnik, sestavljen iz istih točk vrnil enako
ploščino.
Ustvarite tabelo vsaj petih večkotnikov različnih tipov. Za vsakega izračunajte ploščino in obseg ter izpišite podatke in izračunani vrednosti. Seveda preverite tudi pravilnost izračunanih vrednosti. Pri tem si lahko pomagate na primer z GeoGebro
Izpis naj izgleda nekako takole:
Večkotnik [(-3, 2), (-1, 3), (0, 2), (2, 1), (0, 0), (-2, 0), (-3, 2)]:
obseg: 12.36
ploscina: 8.50.
Trikotnik [(2, 4), (3, 6), (6, 4), (2, 4)]:
obseg: 9.84
ploscina: 4.00.
Pravokotnik [(0, 1), (0, 3), (3, 3), (3, 1), (0, 1)]:
obseg: 10.00
ploščina: 6.00.
Izpis se lahko razlikuje od predlaganega, mora pa vsebovati iste informacije. Posnetek zaslona izpisa dodajte v poročilo.
Dodatne naloge (možno, da se kakšna ponovi).
Upravljalec restavracije te prosi za pomoč. Ljudje so ozaveščeni in skrbi jih gensko spremenjena hrana. Moram mu pomagati, da bo izračunal količino GSOja, ki bo zapisana v novem jedilniku.
Kuhar je že sestavil slovar vseh jedi na jedilniku skupaj z njihovimi
sestavinami. Sestavine so tudi podane v obliki slovarja z vnosi
oblike sestavina: količina. Enota pri količini ni podadana (lahko je to
teža, volumen, število kosov, …). Ker se je zelo mudilo, je pri jedeh,
kjer je cela jed ena sama sestavina, pisal le prazno množico. Sestavite
funkcijo odpravi_okrajsave(recepti), ki sestavi in vrne nov slovar,
ki ne vsebuje okrajšav. Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30}, 'solata': dict()}
>>> odpravi_okrajsave(recepti)
{'solata': {'solata': 1}, 'pica': {'sir': 30, 'moka': 80}}
V tistih množicah, ki predstavljajo recepte, je kuhar količine sestavin
podal v gramih. Da bomo lažje računali GSO, jih je treba "normalizirat",
da bo vse v procentih. Napišite funkcijo normaliziraj_kolicine(recepti),
ki kot argument dobi slovar receptov in vrne "normaliziran" slovar receptov
(tj. vsota vseh količin v vsakem receptu naj bo točno 100). Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30} 'solata': dict()}
>>> normaliziraj_kolicine(recepti)
{'solata': {'solata': 100.0},
'pica': {'sir': 27.272727272727273, 'moka': 72.72727272727273}}
Upravljalec restavracije vam je priskrbel še seznam vseh elementarnih
sestavin skupaj z njihovim deležem GSO. Sestavite funkcijo
delez_gso(recepti, elementarne), ki dobi slovar z recepti in slovar
z deleži GSO v elementarnih sestavinah in poračuna deleže GSO v jedeh.
V slovarju elementarnih sestavin so vsaj vse elementarne sestavine, ki
se nahajajo v receptih, lahko pa jih je tudi več. Zgled:
>>> recepti = {'pica': {'moka': 80, 'sir': 30}, 'solata': dict()}
>>> elementarne = {'moka': 70, 'sir': 10, 'solata': 0}
>>> delez_gso(recepti, elementarne)
{'solata': 0.0, 'pica': 53.63636363636364}
Poleg običajnega imajo v restavraciji tudi specialni jedilnik, ki vsebuje
eksotične jedi. Te vsebujejo tudi sestavine, ki prihajajo iz "sumljivih"
dežel in deleža GSO ni mogoče ugotoviti. Napišite še funkcijo
delez_gso_special(recepti, elementarne), ki je podobna kot v prejšni
nalogi, le da vsaki jedi priredi "interval" (tj. par (min_gso, max_gso)).
V minimalnem primeru predpostavimo povsod 0 % GSO, v maximalnem primeru
pa povsod 100 % GSO. Zgled:
>>> recepti = {'pica_special': {'moka': 80, 'sir': 30, 'namaz': 10}, 'solata_special': dict()}
>>> elementarne = {'moka': 70, 'sir': 10, 'solata': 5}
>>> delez_gso_special(recepti, elementarne)
{'pica_special': (49.16666666666667, 57.5), 'solata_special': (0.0, 100.0)}
Pri tej nalogi boste napisali funkcijo, ki bo za dano število vrnila niz z ustrezno rimsko številko. Nato boste napisali še funkcijo, ki bo rimsko številko spremenila nazaj v število.
Preden začnete, si na Wikipediji oglejte članek o rimskih številkah: Rimske številke.
Napišite funkcijo v_rimsko(stevilo), ki kot argument dobi celo
število med 1 in 3999 (vključno z 1 in 3999). Funkcija naj sestavi
in vrne niz, ki vsebuje rimsko številko, ki predstavlja število stevilo.
Zgled:
>>> v_rimsko(2013)
'MMXIII'
Napišite še funkcijo v_arabsko(niz), ki bo dobila niz niz, ki
predstavlja rimsko številko. Funkcija naj naredi ravno obratno kot
funkcija v_rimsko, tj. vrne naj ustrezno število, ki ga predstavlja
dana rimska številka. Če niz ne predstavlja veljavne rimske
številke, naj funkcija vrne None. Zgled:
>>> v_arabsko('MMXIII')
2013
Nasvet: Najprej sestavi slovar, ki kot ključe vsebuje rimske številke, kot vrednosti pa ustrezna števila. Potem le uporabi ta slovar.
Kadar nas zanima, kam se lahko iz danega kraja odpravimo, lahko odpremo zemljevid in pogledamo, v katere kraje nas iz danega kraja vodijo ceste. Recimo iz Celja se lahko odpravimo proti Velenju, Laškem ali Rogaški Slatini, iz Logatca se lahko odpravimo proti Idriji, Postojni in Vrhniki, iz Vrhinike se lahko odpravimo nazaj proti Logatcu ali proti Ljubljani.
Tak zemljevid lahko predstavimo tudi z usmerjenim grafom. Usmerjen graf sestavljata množica vozlišč in množica usmerjenih povezav . Vsaki usmerjeni povezavi pripada vozlišče, ki ga imenujemo začetek povezave, in vozlišče, ki ga imenujemo konec povezave.
Običajno si vozlišča predstavljamo kot točke v ravnini, povezave pa kot puščice med njimi. Puščica je usmerjena od začetnega proti končnemu vozlišču.
Usmerjene grafe lahko predstavimo na več načinov. Lahko ga podamo kot množico vozlišč in seznam parov usmerjenih povezav:
V = {'Logatec', 'Vrhnika', 'Ljubljana', 'Postojna', 'Idrija'}
A = [('Logatec', 'Vrhnika'), ('Logatec', 'Postojna'), ('Logatec', 'Idrija'), ('Vrhnika', 'Logatec'), ('Vrhnika', 'Ljubljana')]
Lahko pa ga podamo v obliki slovarja naslednikov:
{'Logatec': ['Vrhnika', 'Postojna', 'Idrija'], 'Vrhnika': ['Logatec', 'Ljubljana']}
(V zgornjem primeru smo predpostavili, da se iz Postojne, Idrije in Ljubljane, ne da priti nikamor (kar seveda ni res))
Ključi v tem slovarju so vozlišča, vrednost pri posameznem ključu u pa
je seznam vseh vozlišč, ki so nasledniki vozlišča u. (Vozlišče je
naslednik vozlišča , če v digrafu obstaja usmerjena povezava .)
V nadaljevanju predpostavite, da grafi ne bodo imeli izoliranih vozlišč (to so vozlišča, ki niso niti začetek niti konec katere od povezav).
Napišite funkcijo slovar_naslednikov(seznam_povezav), ki kot argument
dobi seznam povezav digrafa, sestavi in vrne pa naj pripadajoči slovar
naslednikov. Zgled:
>>> slovar_naslednikov([('a', 'b'), ('c', 'b'), ('c', 'd'), ('d', 'a'), ('a', 'c')])
{'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']}
Seznami naslednikov naj bodo urejeni.
Sestavite funkcijo seznam_povezav(digraf), ki kot argument dobi
usmerjen graf, ki je podan kot slovar naslednikov. Funkcija naj sestavi
in vrne seznam usmerjenih povezav. (Torej, funkcija seznam_povezav naj
naredi ravno obratno kot funkcija slovar_naslednikov.) Zgled:
>>> seznam_povezav({'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']})
[('a', 'b'), ('a', 'c'), ('c', 'b'), ('c', 'd'), ('d', 'a')]
Seznam povezav, ki ga vrne funkcija, naj bo urejen.
Napišite funkcijo nasprotni_graf(digraf), ki dobi usmerjen graf
v obliki slovarja naslednikov, sestavi in vrne pa naj nasprotni graf
(tudi v obliki slovarja naslednikov). Nasprotni graf grafa ima enako
množico vozlišč kot , povezave pa imajo obrnjeno smer. Zgled:
>>> nasprotni_graf({'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']})
{'a': ['d'], 'c': ['a'], 'b': ['a', 'c'], 'd': ['c']}
Seznami naslednikov naj bodo urejeni.
Usmerjene grafe lahko sestavimo iz večih usmerjenih podgrafov. Vsak posamezen podgraf je predstavljen s slovarjem, za katerega velja, da ima vsako vozlišče le enega naslednika.
Sestavite funkcijo sestavljen_graf(tabela_podgrafov), ki bo iz
dane tabele usmerjenih podgrafov sestavila slovar, ki bo predstavljal
graf v obliki slovarja naslednjikov. Vrednosti naj bodo v
tabelah zapisane v enakem vrstnem redu, kot nastopajo v tabeli podgrafov.
Zgled:
>>> sestavljen_graf([{'a': 'b', 'c': 'b'}, {'a': 'c', 'c': 'd', 'd': 'a'}])
{'a': ['b', 'c'], 'c': ['b', 'd'], 'd': ['a']}
Ukvarjali se bomo z rodovniki (Celjskih grofov in drugih). Rodovnik imamo podan kot slovar, kjer je ključ ime "glave rodbine" vrednost pa tabela imen otrok. Recimo:
rodovnik =
{'Ulrik I.': ['Viljem'], 'Margareta': [], 'Herman I.': ['Herman II.', 'Hans'],
'Elizabeta II.': [], 'Viljem': ['Ana Poljska'], 'Elizabeta I.': [],
'Ana Poljska': [], 'Herman III.': ['Margareta'], 'Ana Ortenburška': [],
'Barbara': [], 'Herman IV.': [], 'Katarina': [], 'Friderik III.': [],
'Herman II.': ['Ludvik', 'Friderik II.', 'Herman III.', 'Elizabeta I.', 'Barbara'],
'Ulrik II.': ['Herman IV.', 'Jurij', 'Elizabeta II.'], 'Hans': [], 'Ludvik': [],
'Friderik I.': ['Ulrik I.', 'Katarina', 'Herman I.', 'Ana Ortenburška'],
'Friderik II.': ['Friderik III.', 'Ulrik II.'], 'Jurij': []}
rodovnik['Friderik II.']
nam torej vrne
['Friderik III.', 'Ulrik II.']
Število otrok
Sestavi funkcijo koliko_otrok(ime, rodovnik), ki za dano ime in
rodovnik vrne število otrok te osebe, oz None, če osebe ni v rodovniku.
Število potomcev
Sestavi funkcijo koliko_potomcev(ime, rodovnik), ki za dano ime in
rodovnik vrne število potomcev te osebe. Če osebe ni v rodovniku, vrni None
Je v rodbini?
Sestavi funkcijo je_v_rodbini(ime, glava_rodbine, rodovnik), ki ugotovi, ali
je oseba z imenom ime v rodbini osebe glava_rodbine.
Kdo se podpisuje najdlje časa?
Sestavi funkcijo najdaljsi_podpis(glava_rodbine, rodovnik), ki ugotovi, kdo
v rodbini osebe glava_rodbine ima najdaljše ime za podpis (torej kompletno
ime).
Kdo ima najkrajše ime?
Sestavi funkcijo najkrajse_ime(glava_rodbine, rodovnik), ki ugotovi, kdo
v rodbini osebe glava_rodbine ima najkrajše ime.
(šteje samo krstno ime, brez "Ortenburga" in "Celja" ter brez številk)?
Globina rodbine
"Globino" rodbine definiramo tako: če nekdo nima otrok, je globina njegove rodbine 1. Če ima otroka, ta pa nima vnukov (ali celo več otrok, ti pa nimajo vnukov), je globina rodbine 2. Če nekdo ima vnuke, vendar nobenega pravnuka, je globina njegove rodbine 3.
Sestavi funkcijo globina(glava_rodbine, rodovnik), ki vrne globino rodbine
osebe glava_rodbine v rodovniku rodovnik
Spodnji program naj bi pretvarjal starost psa iz človeških v pasja leta.
Prvi dve leti so pasja leta enaka 10.5 * človeška leta, nato pa
je vsako nadaljnje pasje leto enako 4 človeškim letom.
V programu se je premešal vrstni red vrstic (zamiki so ostali pravilni).
Popravi vrstni red vrstic, da bo program smiselno deloval.
if c_starost <= 2:
print("Starost mora biti pozitivno število.")
c_starost = int(input("Vnesi starost psa v človeških letih: "))
p_starost = 21 + (c_starost - 2) * 4
if c_starost < 0:
else:
print("Starost psa v pasjih letih je", p_starost)
p_starost = c_starost * 10.5
else:
Spodnji program naj bi za dani mesec izpisal število dni v tem mesecu. V programu se je premešal vrstni red vrstic (zamiki so ostali pravilni). Popravi vrstni red vrstic, da bo program smiselno deloval.
else:
elif mesec in ("januar", "marec", "maj", "julij", "avgust", "oktober", "december"):
if mesec == "februar":
print("Napačno poimenovanje meseca")
print("Število dni: 30 dni")
mesec = input("Vnesi ime meseca: ")
elif mesec in ("april", "junij", "september", "november"):
print("Število dni: 31 dni")
print("Število dni: 28/29 dni")
Spodnji program izračuna vsoto in povprečje celih števil, ki jih uporabnik vnese. V kodi manjkajo zamiki. Popravi kodo, da bo smiselno delovala.
print("Vnesi nekaj celih števil, da bom lahko izračunal njihovo vsoto in povprečje. Vnesi 0, če si zaključil z vnašanjem števil.")
stevec = 0
vsota = 0.0
stevilo = 1
while stevilo != 0:
stevilo = int(input(""))
vsota = vsota + stevilo
stevec += 1
if stevec == 1:
print("Nisi vnesel števil.")
else:
print("Povprečje in vsota vnešenih števil sta:", vsota / (stevec-1), vsota)
Spodnji program izbere naravno število med 1 in 10. Uporabnika pozove, da ugane izbrano število. Uporabnik ugiba, dokler ne najde pravega števila. A program ne deluje pravilno, ker so se vrstice med seboj premešale in se naključno zamaknile. Popravi program, da bo pravilno deloval.
elif iskano_stevilo < ugibanje:
ugibanje = int(input("Ugibaj število med 1 in 10, dokler ne najdeš pravega števila: "))
print("Našel si iskano število!")
print("Iščeš večje število.")
while iskano_stevilo != ugibanje:
if iskano_stevilo > ugibanje:
print("Iščeš manjše število.")
iskano_stevilo, ugibanje = random.randint(1, 10), 0
import random
Spodnja funkcija naj bi računala največji skupni delitelj dveh števil z uporabo Evklidovega algoritma, ne deluje pravilno, ker so vrstice med seboj premešane. Poleg tega so se v funkcijo vrinile nekatere nepotrebne vrstice. Popravi funkcijo, da bo pravilno delovala.
b = a % b
a, b = b, a % b
def gcd(a, b):
a = b
return a
a, b = b - a, a
while b > 0:
''' izracuna najvecji skupni delitelj (ang. greatest common divisor) stevil a in b '''
Za razliko od običajnih družabnih omrežij, deluje nedružabno omrežje Hatebook tako, da si v omrežje vsak dodaja svoje sovražnike. Omrežje predstavimo s slovarjem, pri čemer so ključi osebe, vrednosti pa množice oseb, ki jih te osebe sovražijo.
Primer omrežja:
>>> omrezje = {'Žiga': {'Zoran', 'Vesna', 'Ugo'},
'Zoran': {'Vesna'},
'Vesna': set(),
'Ugo': {'Zoran', 'Žiga', 'Ugo'},
'Tina': {'Vesna'}}
Sestavite funkcijo se_sovrazita(omrezje, oseba1, oseba2), ki vrne True,
kadar osebi sovražita druga drugo, in False sicer.
Primer:
>>> se_sovrazita(omrezje, "Ugo", "Žiga")
True
>>> se_sovrazita(omrezje, "Ugo", "Zoran")
False
Sestavite funkcijo kdo_sovrazi(omrezje, oseba), ki vrne množico oseb,
ki v danem omrežju sovražijo dano osebo.
Primer:
>>> kdo_sovrazi(omrezje, "Vesna")
{"Žiga", "Zoran", "Tina"}
Sestavite funkcijo nesrecniki(omrezje), ki vrne množico oseb, ki
sovražijo same sebe.
Primer:
>>> nesrecniki(omrezje)
"Ugo"
Sestavite funkcijo najbolj_zadrti(omrezje), ki vrne množico vseh oseb,
ki v danem omrežju sovražijo največ oseb.
Primer:
>>> najbolj_zadrti(omrezje)
{"Žiga", "Ugo"}
Sestavljen je razred KompleksnoStevilo z metodama __init__(self, re, im),
lastnostima im inre terrepr(self).
Realni del kompleksnega števila je shranjen v spremenljivki_re, imaginarni pa v_im. Metodarepr(self)predstavi kompleksno
število z nizom oblikeKompleksnoStevilo(re, im)`.
Zgled:
>>> u = KompleksnoStevilo(3, 4)
>>> u
KompleksnoStevilo(3, 4)
Žal so se vrstice v kodi zamešale. uredi jih v pravilni vrstni red. Razen spreminanja vrstnega reda ne naredi nobene druge spremembe
Razredu dodaj metodo __str__(self), ki kompleksno stevilo predstavi z nizom
oblike npr. 3 + 4i
Pri tem bodi pozoren da:
◦ Če je realni ali imaginarni del števila enak 0, naj bo v nizu njegov člen
izpuščen (npr. namesto 2 + 0i pišemo samo 2).
◦ Če je imaginarni del števila enak 1, namesto 1i pišemo samo i. Če je
enak -1namesto -1i pišemo -i.
◦ Če je imaginarni del števila negativen, njegov predznak zamenja +. Torej,
namesto 2 + (-3)i pišemo kar 2 – 3i. Če je realni del enak 0 med predznakom
- in nadaljevanjem ni presledka. Torej namesto - 3i pišemo -3i.
Zgled:
>>> u = KompleksnoStevilo(3, 4)
>>> print(u)
3 + 4i
>>> v = KompleksnoStevilo(2, 0)
>>> print(v)
2
>>> w = KompleksnoStevilo(0, -4)
>>> print(w)
-4i
>>> w = KompleksnoStevilo(0, 1)
>>> print(w)
i
>>> y = KompleksnoStevilo(-2, -6)
>>> print(y)
-2 - 6i
>>> z = KompleksnoStevilo(0, 0)
>>> print(z)
0
Opozorilo: To in vse ostale podnaloge
začnite s class KompleksnoStevilo(KompleksnoStevilo)
Da ne bo težav pri testiranju, pri vseh podnalogah začnemo z
class Ulomek(Ulomek):
Seveda pa 1. podnalogo še vedno začnemo z
class Ulomek:
Sestavite razred Ulomek, s katerim predstavimo ulomek. Števec in
imenovalec sta celi števili, pri čemer je imenovalec vedno pozitiven.
Ulomki naj bodo vedno okrajšani.
Do števca lahko pridemo preko lastnosti st, do imenovalca pa preko lastnosti
im. Če poskusimo spremeniti števec ali imenovalec (torej lastnosti st ali im)
naj koda sproži napako z obvestilom "Obstoječega ulomka ne moremo spreminjati"
Zgled:
>>> u = Ulomek(5, -20)
>>> u.st
-1
>>> u.im
4
>>> u.st = 4
... Exception("Obstoječega ulomka ne moremo spreminjati")
Trenutna implementacija razreda Ulomek objekt Ulomek(5, 20) izpiše z nizom
oblike <__main__.Ulomek object at 0x000002CB41CDD2B0>, iz katerega ne moremo
razbrati za kateri ulomek gre. Kako naj se objekt našega razreda izpiše, lahko
sami določimo z metodama __str__ in __repr__. Kako metodi delujeta in
kakšna je razlika med njima si poglejte v
videu.
Sestavite metodo __str__(self), ki predstavi ulomek z nizom
oblike 'st/im'. Zgled:
>>> u = Ulomek(5, 20)
>>> print(u)
1/4
Sestavite še metodo __repr__(self), ki predstavi ulomek z nizom
oblike 'Ulomek(st, im)'. Zgled:
>>> u = Ulomek(5, 20)
>>> u
Ulomek(1, 4)
Z metodo Monte Carlo lahko računamo tudi ploščine. Pri tem gre v grobem za to, da naključno izbiramo točke na nekem pravokotniku in štejemo, koliko točk je takih, da "spadajo" k ploščini. Če razmerje med "zadetki" in vsemi točkami pomnožimo s ploščino pravokotnika, dobimo približek za ploščino območja.
Ploščino pod enim valom funkcije sinus (enaka je 2) lahko približno izračunamo tudi tako, da naključno izbiramo točke na pravokotniku [0, Pi] x [0, 1] in s Pi pomnožimo razmerje med točkami pod valom in vsemi točkami.
Sestavi funkcijo ploscina_val(n), ki izračuna ploščino vala funkcije
sin(x) po opisani metodi. Število naključnih točk
funkcija dobi kot parameter.