Professional Documents
Culture Documents
Testi: Rekurzivni Nim - Rim
Testi: Rekurzivni Nim - Rim
Testi: Rekurzivni Nim - Rim
Napisali boste nekaj funkcij, ki ste jih pisali za nalogo Nim - le da bodo tokrat rekurzivne.
Testi
Testi: testi-rim.py
Obvezna naloga
Napiši naslednje funkcije:
Je to res?
Rešitev
Vsota števil v seznamu je enaka vrednosti prvega elementa, ki ji prištejemo vsoto ostalih
elementov. Reč se ustavi, ko je seznam prazen; vsota elementov v njem je 0.
def vsota(s):
if not s:
return 0
else:
return s[0] + vsota(s[1:])
Rokohitrsko, zavedajoč se, da je False isto kot 0:
def vsota(s):
return s != [] and s[0] + vsota(s[1:])
Seznam s vsebuje x, če ni prazen in je x prvi element ali pa ostanek vsebuje x. Reč se
ustavi, ko je seznam prazen in Python ne gre preverjat ostanka pogoja.
def najvecja_potenca(n):
if n == 1:
return 1
return 2 * najvecja_potenca(n // 2)
Dodatna naloga
razbij(n) vrne seznam potenc števila 2, ki se seštejejo v podano število n; vsaka
potenca lahko nastopa le enkrat. Klic razbij(22) vrne [16, 4, 2]. Števila naj bodo
urejena v padajočem vrstnem redu. Nalogo reši tako, da najprej s prejšnjo funkcijo
poiščeš največjo potenco. Nato poiščeš seznam, ki predstavlja razbitje ostanka, in
mu (spredaj) dodaš to potenco.
brez(s, x) prejme nek seznam s in vrne nov seznam, ki je enak podanemu
seznamu, a brez x-ov. Klic brez([5, 4, 1, 2, 1, 1, 3], 1) vrne [5, 4, 2, 3]. Te
funkcije ni bilo v originalni nalogi Nim, a ti lahko pride prav pri naslednjem
paketku nalog.
Rešitev
Spet naredimo natančno tako, kot pravi namig v nalogi: poiščemo največjo potenco ( p), ki
gre v n in potem razbijemo, kar ostane od n-ja. Končamo, ko je n nič in ni česa razbijati,
tako da vrnemo prazen seznam.
def razbij(n):
if n == 0:
return []
p = najvecja_potenca(n)
return [p] + razbij(n - p)
Funkcijo brez bomo razpisali lepo počasi. Če je s prazen, vrnemo prazen seznam. Sicer pa
imamo dve možnosti: če je prvi element ravno x, vrnemo ostanek brez x-a. Če je prvi
elemement kaj drugega, pa vrnemo prvi element in ostanek brez x-a.
Rešitev
razlika je ena lepših. Rekurzija bo tekla po s-ju: v vsakem klicu se bomo znebili prvega
elementa s-ja.
Če s ni prazen, moramo ločiti dva primera. Če je prvi element t-ja v s-ju (uporabili bomo
rekurzivno funkcijo vsebuje), bomo vrnili razliko med s-jem brez tega elementa (ker ga je
potrebno odstraniti od tam) in t-jem brez prvega elementa.
def razbij_seznam(s):
if not s:
return []
return [razbij(s[0])] + razbij_seznam(s[1:])
def zdruzi_sezname(ss):
if not ss:
return []
return razlika(ss[0], zdruzi_sezname(ss[1:]))