MPZI_predavanje_14

2449 days ago by fresl

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]
  • umjesto funkcije .extend() može se upotrijebiti operator +=:
       
[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]
  • dvije se liste mogu nadovezati operatorom +:
       
[-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, lnova 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

  • $r \leftarrow 0$
  • $r \leftarrow r + l_0 = 0 + l_0$
  • $r \leftarrow r + l_1 = (0 + l_0) + l_1$
  • $r \leftarrow r + l_2 = ((0 + l_0) + l_1) + l_2$
  • $\cdots$
  • $r \leftarrow r + l_{n-1} = (\cdots (((0 + l_0) + l_1) + l_2)\cdots) + l_{n-1}$

... 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:

  • $r \leftarrow x_0$,
  • $r \leftarrow f (r, l_0) = f (x_0, l_0)$
  • $r \leftarrow f (r, l_1) = f (f (x_0, l_0), l_1)$
  • $r \leftarrow f (r, l_2) = f (f (f (x_0, l_0), l_1), l_2)$
  • $\cdots$
  • $r \leftarrow f (r, l_{n-1}) = f (\cdots(f (f (f (x_0, l_0), l_1), l_2)\cdots), l_{n-1})$

 

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:

  • $r \leftarrow f (l_0, l_1)$
  • $r \leftarrow f (r, l_2) = f (f (l_0, l_1), l_2)$
  • $\cdots$
  • $r \leftarrow f (r, l_{n-1}) = f (\cdots(f (f (f (l_0, l_1), l_2), l_3)\cdots), l_{n-1})$

 

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:

  1. temeljni dio sa slučajem ili slučajevima koji se mogu neposredno izračunati,
  2. rekurzivni dio koji je pak sastavljen od tri koraka:
    1. podjela zadaće u jednostavnije ili manje (pod)zadaće,
    2. rješavanje svake od tih (pod)zadaća pozivom funkcije,
    3. sastavljanje rješenjâ (pod)zadaća u rješenje zadaće


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