Naloge z rešitvami
Transakcije
V začetku je imela Ana štiri zlatnike, Berta 8 in Cilka 10,
torej [('Ana', 4), ('Berta', 8), ('Cilka', 10)].
Nato je dala Cilka Ani 3 zlatnike; potem je dala Cilka Ani
še 2; na koncu je dala Ana Berti 2, kar zapišemo
[('Cilka', 'Ana', 3), ('Cilka', 'Ana', 2), ('Ana', 'Berta', 2)].
Kdo ima na koncu največ? Napišite funkcijo transakcije(zacetek, dajatve), ki dobi zgornja seznama in vrne ime najbogatejše osebe po koncu transakcij. Če je na koncu več enako bogatih najbogatejših oseb, naj vrne poljubno izmed njih.
Najboljše bo, da se naloge lotite takole:
- pretvorite seznam v slovar - v gornjem primeru, recimo
v
{'Ana': 4, 'Berta': 8, 'Cilka': 10}- in ga izpišite, da boste videli, da ste naredili prav. - napišite del funkcije, ki "izvede" transakcije in izpišite
rezultat, da boste videli, da ste naredili prav. V gornjem
primeru se mora izpisati
{'Ana': 7, 'Berta': 10, 'Cilka': 5} - v slovarju poiščete najbogatejšo osebo - torej ključ, pri katerem je vrednost največja.
Primer klica:
>>> transakcije([('Ana', 4), ('Berta', 8), ('Cilka', 10)],
[('Cilka', 'Ana', 3), ('Cilka', 'Ana', 2), ('Ana', 'Berta', 2)])
Berta
Natakar
Ko je prišel natakar, so naročile:
- Ana je naročila torto,
- Berta je naročila krof,
- Cilka je naročila kavo,
- Ana je naročila še kavo,
- Berta je rekla, da ne bo krofa,
- Cilka je rekla, da ne bo torte (no, saj je niti ni naročila; to natakar mirno ignorira),
- Berta je naročila torto. Vse skupaj zapišemo takole:
[("Ana", "torta"), ("Berta", "krof"), ("Cilka", "kava"), ("Ana", "kava"), ("Berta", "-krof"), ("Cilka", "-torta"), ("Berta", "torta")].
Seznam torej vsebuje pare nizov (oseba, jed), pri čemer se jed včasih začne z "-", kar pomeni, da stranka prekliče naročilo te jedi oz. pijače. Napiši funkcijo narocila(s), ki prejme takšen seznam in vrne slovar, katerega ključi so imena strank, vrednost pri vsakem ključu pa je seznam vsega, kar mora stranka na koncu dobiti.
Primer:
>>> narocila([('Ana', 'torta'), ('Berta', 'krof'), ('Cilka', 'kava'), ('Ana', 'kava'), ('Berta', '-krof'), ('Cilka', '-torta'), ('Berta', 'torta')])
{'Cilka': ['kava'], 'Berta': ['torta'], 'Ana': ['torta', 'kava']}
>>> narocila([('Ana', 'torta'), ('Ana', '-torta')])
{'Ana': []}
>>> narocila([('Ana', '-torta')])
{'Ana': []} # Tu sme funkcija vrniti tudi prazen slovar, {}
Najpogostejše
Napišite funkcijo najpogostejse(s), ki vrne besedo in znak, ki se v podanem nizu največkrat pojavita. V nizu 'in to in ono in to smo mi' se največkrat pojavita beseda 'in' in znak ' ' (presledek).
Primer:
>>> najpogostejse('aa bb aa')
('aa', 'a')
>>> najpogostejse('in to in ono in to smo mi')
('in', ' ')
Prvo nalogo bomo reševali po korakih, da dobite občutek, kako se pristopi k taki nalogi in kako se dela s slovarji. Zraven boste dobili še malo prakse pri delu s funkcijami in razumeli (vsaj upam), zakaj so koristne.
Korak 1: Frekvence
Napišite funkcijo frekvence(sez), ki sprejme seznam sez in vrne slovar. Ključi slovarja naj bodo elementi seznama, vrednosti pa njihove frekvence v seznamu. S psevdokodo bi naša funkcija izgledala nekako takole:
- Pripravim prazen slovar.
- Z zanko se sprehodim preko seznama.
-
- Če je element seznama že v slovarju, mu prištejem vrednost za 1.
- Če elementa še ni, ga dodam in nastavim ustrezno frekvenco.
- Vrnem slovar.
Korak 2: Maks element
Napišite funkcijo maks_element(sez), ki sprejme seznam sez in vrne element seznama, ki se najpogosteje pojavlja. Postopek si lahko razdelimo na dva koraka:
- Izračunamo frekvence elementov v seznamu in jih shranimo v slovar.
- Izberemo tisti ključ, ki ima največjo frekvenco. Če vemo, da se s
forzanko sprehodimo preko ključev slovarja, je ta problem zelo podoben nalogi, kjer smo iskali najmanjši pozitivni element v seznamu.
Korak 3: Najpogostejše
Napišite funkcijo najpogostejse(s). Namig: niz lahko razbijete na seznam besed z metodo split(). Npr.:
s = "kaj to naredi?"
besede = s.split()
Če pa želite niz razbiti na seznam znakov, potem lahko napišete list(niz). Ali je to za našo nalogo sploh potrebno?
* Najpogostejše urejene
Ta naloga je malo težja za tiste s hitrimi prsti. Napišite funkcijo najpogostejse_urejene, ki vrne vse besede in črke, ki se v podanem nizu pojavijo, urejene po številu pojavitev (besede in črke z enakim številom pojavitev uredite po abecednem vrstnem redu).
>>> najpogostejse_urejene('aa bb aa')
(['aa', 'bb'], ['a', ' ', 'b'])
>>> najpogostejse_urejene('in to in ono in to smo mi')
(['in', 'to', 'mi', 'ono', 'smo'], [' ', 'o', 'i', 'n', 'm', 't', 's'])
Družinsko drevo
V datoteki family.txt je spravljeno družinsko drevo. V vsaki vrstici sta zapisani dve imeni: ime starša in ime otroka. Tako nam vrstica 'bob mary' pove, da je Bob Maryjin oče, vrstica 'bob tom' pa, da je Bob Tomov oče, itd...
Kako dostopamo do datoteke? Če želimo datoteko prebrati po vrsticah, potem enostavno napišemo:
f = open("family.txt", "rt")
for vrstica in f:
print(vrstica)
Naloga: Napišite funkcijo family_tree(file), ki sprejeme datoteko, odprto za branje, v kateri je shranjeno družinsko drevo in vrne slovar v katerem je za vsakega starša spravljen seznam vseh njegovih otrok.
>>> family_tree(open('family.txt'))
{'renee': ['rob', 'bob'], 'ken': ['suzan'], 'rob': ['jim'], 'sid': ['rob', 'bob'], ... , 'bob': ['mary', 'tom', 'judy']}
Naloga: Napišite funkcijo children(tree, name), ki v družinskem drevesu tree vrne seznam vseh otrok osebe. V primeru, da oseba nima otrok vrnite prazen seznam.
>>> tree = family_tree(open('family.txt'))
>>> children(tree, 'alice')
['mary', 'tom', 'judy']
>>> children(tree, 'mary')
[]
Naloga: Napišite funkcijo grandchildren(tree, name), ki vrne seznam vseh vnukov in vnukinj osebe.
>>> grandchildren(tree, 'renee')
['jim', 'mary', 'tom', 'judy']
Naloga: Naslednja funkcija je malo zahtevnejša od ostalih, zato jo lahko preskočite. Napišite funkcijo successors(tree, name), ki vrne seznam vseh naslednikov osebe.
>>> successors(tree, 'tom')
['ken', 'suzan']
>>> successors(tree, 'sid')
['rob', 'bob', 'jim', 'mary', 'tom', 'judy', 'ken', 'suzan']
Naključno generirano besedilo
Napisati želimo program, ki bo naključno generiral besedilo. Seveda ni dobro, da si samo naključno izbiramo besede in jih lepimo skupaj, saj bi tako dobili nekaj povsem neberljivega. Naloge se bomo lotili malo pametneje. Recimo, da ima program na voljo nek tekst ('in to in ono smo mi'), iz katerega se lahko uči. Naš naključni tekst bomo začeli s poljubno besedo, recimo to. Nadaljujemo tako, da se vprašamo katere besede se v učnem tekstu pojavijo za besedo to. V našem primeru je to samo beseda in. Postopek nato ponovimo z besedo in. Če kakšni besedi v učnem tekstu sledi več kot samo ena beseda, izberemo naključno. Naloge se bomo lotili po korakih:
Napišite funkcijo nasledniki(txt), ki za vsako besedo b v nizu txt zgradi seznam besed, ki v tekstu nastopijo za besedo b. Nekaj primerov:
>>> nasledniki('in in in in')
{'in': ['in', 'in', 'in']}
Za besedo in se na treh mestih pojavi beseda in.
>>> nasledniki('in to in ono in to smo mi')
{'smo': ['mi'], 'to': ['in', 'smo'], 'ono': ['in'], 'in': ['to', 'ono', 'to']}
Za besedo smo se pojavi samo beseda mi, medtem ko se recimo za besedo to pojavita tako beseda smo kot tudi beseda in.
Sedaj pa napišite še funkcijo tekst(nasl, num_besed), ki sprejme slovar, ki ga ustvari funkcija nasledniki in generira naključno besedilo dolgo num_besed besed.
Vaš program lahko testirate na Orwellovi noveli.
>>> import urllib.request
>>> txt = urllib.request.urlopen('http://squeeb1134.tripod.com/1984.txt').read().decode('utf8')
>>> tekst(nasledniki(txt), 20)
'Big Brother had been drained out of the hands of me for his heart banged, seeming to grow less. Always'
Zaradi naključnosti je nalogo tekst težko preveriti z unittesti. Priložen test preveri le najbolj osnovne lastnosti.