O listama i o rekurziji
Baratanje listama
Pridruživanje i kopiranje lista
Pridruživanjem liste novoj varijabli, ta varijabla postaje samo drugi naziv iste liste:
[1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] |
[1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] |
... rekosmo, samo drugi naziv:
[1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] |
Nova se lista—istoga sadržaja—dobiva kopiranjem:
[1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] |
[1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3.1415926535897932385, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3/2, 'zadnji element'] [1, 2.00000000000000, 300, 3.1415926535897932385, 'zadnji element'] |
Za ugniježđene liste treba upotrijebiti funkciju deepcopy():
[1, 2.00000000000000, 'a', 3/2, 'zadnji element'] [1, 2.00000000000000, 'a', 3/2, 'zadnji element'] |
[1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] |
[1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'pet'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'zadnji element'] [1, 2.00000000000000, 'tri', 3/2, 'pet'] |
Tvorba lista i dodavanje komponenata
.append() — dodavanje komponente na kraj liste:
0 [] 1 [1] 2 [1, 8] 3 [1, 8, 27] 4 [1, 8, 27, 64] 5 [1, 8, 27, 64, 125] 6 [1, 8, 27, 64, 125, 216] 0 [] 1 [1] 2 [1, 8] 3 [1, 8, 27] 4 [1, 8, 27, 64] 5 [1, 8, 27, 64, 125] 6 [1, 8, 27, 64, 125, 216] |
[1, 8, 27, 64, 125, 216] [1, 8, 27, 64, 125, 216] |
sažeta tvorba liste (list comprehension):
[1, 8, 27, 64, 125, 216] [1, 8, 27, 64, 125, 216] |
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13] [13, 13, 13, 13, 13, 13, 13, 13, 13, 13] |
|
[0, 2, 4, 6, 8] [0, 2, 4, 6, 8] |
.extend() — dodavanje liste na kraj liste:
[1, 8, 27, 64, 125, 216] [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728] [1, 8, 27, 64, 125, 216] [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728] |
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] |
[-64, -27, -8, -1, 0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] [-64, -27, -8, -1, 0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] |
... pribrojnici se pritom ne mijenjaju:
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] |
.insert() — umetanje komponente na određeno mjesto u listi:
[-1, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] [-1, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] |
.pop() — uklanjanje komponente s određenoga mjesta u listi:
27 27 |
[-1, 1, 8, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] [-1, 1, 8, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096] |
Funkcije map(), reduce() i filter()
Funkcija map()
... ako je $f$ funkcija jedne varijable, a lista $l$ ima komponente $l_0,\,l_1,\,\ldots,\, l_{n-1}$, rezultat poziva map (f, l) nova je lista $[f(l_0),\,f(l_1),\,\ldots,\, f(l_{n-1})]$.
[1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] |
|
[1, 8, 27, 64, 125, 216, 343, 512, 729] [1, 8, 27, 64, 125, 216, 343, 512, 729] |
... isto, primjenom petlje for:
[1, 8, 27, 64, 125, 216, 343, 512, 729] [1, 8, 27, 64, 125, 216, 343, 512, 729] |
... isto, primjenom sažete tvorbe liste:
[1, 8, 27, 64, 125, 216, 343, 512, 729] [1, 8, 27, 64, 125, 216, 343, 512, 729] |
... štoviše:
[1, 8, 27, 64, 125, 216, 343, 512, 729] [1, 8, 27, 64, 125, 216, 343, 512, 729] |
Neimenove funkcije (lambda–funkcije)
<function <lambda> at 0x7f94ac22d5f0> <function <lambda> at 0x7f94ac22d5f0> |
27 27 |
5 5 |
map() i lambda
[1, 8, 27, 64, 125, 216, 343, 512, 729] [1, 8, 27, 64, 125, 216, 343, 512, 729] |
[13, 13, 13, 13, 13, 13, 13, 13, 13] [13, 13, 13, 13, 13, 13, 13, 13, 13] |
Ako je $f$ funkcija dviju varijabli i ako su $a = [a_0,\,a_1,\,\ldots,\,a_{n-1}]$ i $b = [b_0,\,b_1,\,\ldots,\,b_{n-1}]$ dvije liste s jednakim brojem komponenata, onda je rezultat poziva map (f, a, b) lista $[f(a_0,b_0),\, f(a_1,b_1),\,\ldots,\,f(a_{n-1},b_{n-1})]$.
[10, 10, 10, 10, 10, 10, 10, 10, 10] [10, 10, 10, 10, 10, 10, 10, 10, 10] |
... isto, primjenom petlje:
[1, 2, 3, 4, 5, 6, 7, 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1] [10, 10, 10, 10, 10, 10, 10, 10, 10] [1, 2, 3, 4, 5, 6, 7, 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1] [10, 10, 10, 10, 10, 10, 10, 10, 10] |
[0, -7/9, -11/4, -45/7, -38/3, -23, -81/2, -217/3, -140] [0, -7/9, -11/4, -45/7, -38/3, -23, -81/2, -217/3, -140] |
(Domaća zadaća: napišite funkciju something() primjenom sažetih tvorbi lista i primjenom petlji for :o)
Funkcija reduce()
... umjesto petlje
45 45 |
... to jest
... možemo primijeniti funkciju
45 45 |
... općenito, neka su $f$ funkcija dviju varijabli, $l = [l_0,\,l_1,\,\ldots,\, l_{n-1}]$ i $x_0$ broj; rezultat $r$ poziva reduce (f, l, x0) izračunava se na sljedeći način:
Duljina vektora $\mathbf{v}$: $v = \|\mathbf{v}\| = \displaystyle\sqrt{\sum_{i=0}^{n-1}v_i^2}$
|
25 25 |
(7, 24) (7, 24) |
25 25 |
25 25 |
Drugi oblik poziva funkcije reduce() — bez trećega parametra:
45 45 |
... što je, primjenom petlje,
45 45 |
... dakle, za funkciju $f$ dviju varijabli i $l = [l_0,\,l_1,\,\ldots,\, l_{n-1}]$, rezultat $r$ poziva reduce (f, l) izračunava se na sljedeći način:
Skalarni umnožak vektora $\mathbf{u}$ i $\mathbf{v}$: $s = \mathbf{u}\cdot\mathbf{v} = \displaystyle\sum_{i=0}^{n-1} u_i\,v_i$
|
(1, 2, -11, 3/2, 6, -1/2, 5, 1/2, 0, 2) (2/3, 0, -11, -1, -1, 1, -2/3, 4, 0, -15/2) (1, 2, -11, 3/2, 6, -1/2, 5, 1/2, 0, 2) (2/3, 0, -11, -1, -1, 1, -2/3, 4, 0, -15/2) |
292/3 292/3 |
292/3 292/3 |
292/3 292/3 |
Funkcija filter()
... ako su $p$ relacijska ili logička funkcija (takozvani predikat — funkcija čije su vrijednosti True ili False) i $l$ lista, onda je rezultat poziva filter (p, l) nova lista koja sadrži one komponente $l_i$ liste $l$ za koje je $p(l_i) =$ True.
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
... isto, primjenom petlje:
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
... isto, primjenom sažete tvorbe liste:
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
Rekurzivne funkcije
Neformalno, funkcija koja poziva samu sebe naziva se rekurzivnom funkcijom.
Strože i potpunije, definicija rekurzivne funkcije sastavljena je od dva dijela:
Izračunavanje cjelobrojne potencije
„Naivni” algoritam
$n > 0$
$x^n =\, x\, \underbrace{\times\, x\times \cdots\times x}_{n-1\;\text{puta}}$
složenost algoritma: $\mathcal{O}(n)$ množenja
Rješenje pomoću petlje
|
8 8 |
81 81 |
-524288 -524288 |
95367431640625 95367431640625 |
Rješenje pomoću rekurzije
rekurzivni dio: $x^n =\, x\times x^{n-1}$
temeljni dio: $x^1 = x$
|
8 8 |
81 81 |
-524288 -524288 |
95367431640625 95367431640625 |
Učinkovitiji algoritam
$\begin{array}{ll}
n\;\;\text{paran:} & x^n \:=\: x^{\,2\,n/2} \:=\: x^{n/2}\!\times x^{n/2} \:=\: \big(\,x^{n/2}\,\big)^{2} \\
n/2\;\;\text{paran:} & x^n \:=\: x^{\,2\cdot 2\cdot n/4} \:=\: \big(\,x^{n/4}\!\times x^{n/4}\,\big)\!\times \big(\,x^{n/4}\!\times x^{n/4}\,\big) \:=\: \big(\,x^{n/4}\,\big)^{2}\!\times \big(\,x^{n/4}\,\big)^{2} \:=\: \big(\big(\,x^{n/4}\,\big)^{2}\,\big)^{2} \\
n = 2^k: & x^n \:=\: x^{2^k} \:=\: \underbrace{\big(\cdots\big(\,x^2\,\big)^{2}\cdots\big)^{2}}_{k\:\text{puta}}\\
\phantom{x} \\
n\;\;\text{neparan:} & x^n \:=\: x\times\big(\,x^{(n-1)/2}\,\big)^2
\end{array}$
složenost algoritma: $\mathcal{O}(\log_2n)$ množenja/kvadriranja
|
8 8 |
81 81 |
-524288 -524288 |
95367431640625 95367431640625 |
4 4 |
4 4 |
... i još neke sitnice
$n = 0$
$\begin{array}{lll} x \ne 0: & & x^0 = 1 \\ x = 0: & & \text{nedefinirano}^* \end{array}$
$^*$ hmm ... prisjetite se napomene u predavanju 11.
$n < 0$
$n = -m$ za $m>0$, pa je $x^n \,=\, x^{-m} \,=\, \dfrac{1}{x^m} \,=\, \left(\dfrac{1}{x}\right)^{\!m} $
|
1 1 |
NaN NaN |
1/524288 1/524288 |
1.90734863281250e-6 1.90734863281250e-6 |
1/95367431640625 1/95367431640625 |
1.04857600000000e-14 1.04857600000000e-14 |
|