Naloge - funkcijsko programiranje
V teh vajah najdete tudi nekaj nalog, ki smo jih reševali tudi že v prejšnjih nalogah. Sedaj bomo te naloge reševali na funkcijski način. Ko rešite, lahko primerjate rešitev z vašo proceduralno rešitvijo.
V teh nalogah je raba vsakršnih zank strogo prepovedana. Vse naloge rešujemo s funkcijami map
, filter
, in reduce
.
Kvadriraj
Napišite funkcijo kvadriraj(xs)
, ki kvadrira vsako število v seznamu xs.
>>> kvadriraj([1, 2, 3, 4, 5])
[1, 4, 9, 16, 25]
Rešitev
def kvadriraj(xs):
return list(map(lambda x: x ** 2, xs))
Samo pozitivna
Napišite funkcijo samo_pozitivna(xs)
, ki vrne seznam vseh pozitivnih števil.
>>> samo_pozitivna([-1, 5, -2, -1, 7, 0])
[5, 7]
Rešitev
def samo_pozitivna(xs):
return list(filter(lambda x: x > 0, xs))
Vsota števil
Napišite funkcijo vsota(xs)
, ki izračuna vsoto števil v seznamu.
>>> vsota([-1, 5, -2, -1, 7, 0])
8
Rešitev
def vsota(xs):
return reduce(lambda acc, x: acc + x, xs)
Produkt sodih števil
Napišite funkcijo produkt_sodih(xs)
, ki izračuna produkt vseh sodih števil v seznamu xs. Funkcija naj za prazen seznam vrne 1
.
>>> produkt_sodih([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
3840
Rešitev
def produkt_sodih(xs):
return reduce(lambda acc, x: acc * x, filter(lambda x: x % 2 == 0, xs))
Največji
Napišite funkcijo najvecji(xs)
, ki vrne največje število v seznamu xs. V tej nalogi je prepovedano uporabljati funkcijo max
in njene ekvivalente. Funkcija za prazen seznam ni definirana.
>>> najvecji([5, 1, -6, 6, -7, 2])
5
Rešitev
def najvecji(xs):
return reduce(lambda acc, x: x if x > acc else acc, xs)
Največji absolutist
Napišite funkcijo naj_abs(xs)
, ki vrne največje število po absolutni vrednost v seznamu xs. V tej nalogi je prepovedano uporabljati funkcijo max
in njene ekvivalente.
>>> naj_abs([5, 1, -6, 6, -7, 2])
-7
Rešitev
def naj_abs(xs):
return reduce(lambda acc, x: x if abs(x) > abs(acc) else acc, xs)
Najdaljša beseda
Napiši funkcijo najdaljsa(s)
, ki vrne najdaljšo besedo v nizu s
. Pomagajte si z metodo split()
.
>>> najdaljsa('an ban pet podgan')
'podgan'
Rešitev
def najdaljsa(s):
return reduce(lambda acc, s: s if len(s) > len(acc) else acc, s.split(" "))
Nalogo lahko rešimo tudi na drug način
def najdaljsa(s):
besede = s.split(" ")
kandidati = zip(besede, map(len, besede))
najdaljsa_beseda = reduce(lambda acc, x: x if x[1] > acc[1] else acc, kandidati)
return najdaljsa_beseda[0]
Sumljive besede
Napiši funkcijo sumljive(s)
, ki vrne seznam vseh sumljivih besed v danem nizu. Beseda je sumljiva, če vsebuje tako črko u kot črko a.
>>> sumljive('Muha pa je rekla: "Tale juha se je pa res prilegla, najlepša huala," in odletela.')
['Muha', 'juha', 'huala,"']
Rešitev
def sumljive(s):
return list(filter(lambda w: "u" in w and "a" in w, s.split(" ")))
Največji podseznam
Napiši funkcijo, ki vrne podseznam z največjo vsoto elementov. Za gornji seznam mora funkcija vrniti [8, 2]
, saj je to podseznam z največjo vsoto, namreč 10
. Funkcija za prazen seznam ni definirana.
>>> najvecji_podseznam([[1, 1, 1], [1, 1]])
[1, 1, 1]
>>> najvecji_podseznam([[2, 4, 1], [3, 1], [], [8, 2], [1, 1, 1, 1]])
[8, 2]
Rešitev
def najvecji_podseznam(xs):
return reduce(lambda acc, x: x if sum(x) > sum(acc) else acc, xs)
Cezarjeva šifra
Napišite program, ki podan niz zašifrira z uporabo cezarjeve šifre. Preden se lotite naloge, se je morda vredno pozanimati kaj počneta funkciji ord in chr. Predpostavite lahko, da niz s
vsebuje le male črke angleške besede in presledke.
>>> cezar("the quick brown fox jumps over the lazy dog")
"wkh txlfn eurzq ira mxpsv ryhu wkh odcb grj"
Rešitev
def cezar(s):
def _replace(l):
return l if l == " " else chr(((ord(l) - ord("a") + 3) % 26) + ord("a"))
return "".join(map(_replace, s))
Palindrom
Napišite funkcijo palindrom(s)
, ki preveri, ali je niz s
palindrom. Pomagajte si s funkcijo reversed
. V rešitvi lahko uporabite funkcijo all
, lahko pa za vajo implementirate tudi svojo verzijo.
>>> palindrom("pericarezeracirep")
True
>>> palindrom("perica")
False
Rešitev
def palindrom(s):
return _all(map(lambda x: x[0] == x[1], zip(s, reversed(s))))
def _all(xs):
return reduce(lambda acc, x: acc and x, xs)
Lokalni maksimum
Napišite funkcijo lokalni_maksimum(xs)
, ki poišče vse lokalne maksimume v seznamu števil. Število je lokalni maksimum takrat, ko je večje od številke na levi in številke na desni strani.
>>> lokalni_maksimum([2, 9, 5, 6, 1])
[9, 6]
>>> lokalni_maksimum([2, 3, 4, 1, 5])
[4]
>>> lokalni_maksimum([1, 2, 3, 4, 5])
[]
Rešitev
def lokalni_maksimum(xs):
kandidati = zip(xs, xs[1:], xs[2:])
maksimumi_terke = filter(lambda x: x[1] > x[0] and x[1] > x[2], kandidati)
return list(map(lambda x: x[1], maksimumi_terke))
Hladilnik
Napišite funkcijo stanje_hladilnika(zacetno_stanje, dogodki)
, ki sprejme začetno stanje hladilnika in seznam dogodkov, ki vplivajo na stanje v hladilniku. Funkcija naj vrne končno stanje hladilnika.
Stanje hladilnika beležimo s slovarjem, kjer je ključ slovarja posamezen izdelek, vrednost pa količina tega izdelka. Dogodki so lahko dveh tipov: "porabi", ki zniža količino izdelka v hladilniku, ter "kupi", ki poviša količino izdelka v hladilniku.
Ker je cilj naloge spoznavanje funkcijskih principov programiranja, naj bo to čarobni hladilnik, ki ima lahko tudi negativne količine posameznih izdelkov (npr. hladilnik ima lahko tudi -4 litre mleka).
>>> hladilnik = {"kruh": 5, "mleko": 3}
>>> dogodki = [
("porabi", "mleko", 0.2),
("kupi", "mleko", 3),
("kupi", "kruh", 2),
("kupi", "sir", 2),
("porabi", "kruh", 0.2),
("porabi", "sir", 0.3),
]
>>> stanje_hladilnika(hladilnik, dogodki)
{'kruh': 6.8, 'mleko': 5.8, 'sir': 1.7}
Rešitev
def obdelaj_dogodek(stanje, dogodek):
vrsta_dogodka, izdelek, kolicina = dogodek
if vrsta_dogodka == "kupi":
stanje[izdelek] = stanje.get(izdelek, 0) + kolicina
elif vrsta_dogodka == "porabi":
stanje[izdelek] = stanje.get(izdelek, 0) - kolicina
return stanje
def stanje_hladilnika(zacetno_stanje, dogodki):
return reduce(obdelaj_dogodek, dogodki, zacetno_stanje)
Binarna števila
Napišite funkcijo v_desetisko
, ki pretvori binarno število podano s seznamom v desetiško.
>>> v_desetisko([0, 0, 1, 0, 1])
5
Rešitev
def v_desetisko(xs):
return reduce(lambda acc, x: acc + 2 ** x[0] * x[1], enumerate(reversed(xs)), 0)