Matrici Numpy 2 - Esercizi

Scarica zip esercizi

Naviga file online

Vediamo ora alcuni esercizi. I primi avranno soluzioni forniti in due versioni: la prime versioni solitamente usano cicli for ed sono quindi lente, la seconde denominate ‘pro’ evitano i cicli utilizzando tutti gli strumenti offerti da numpy. In particolare in molti casi puoi ottenere programmi molto efficienti e compatti usando in modo furbo le slice.

ATTENZIONE

Gli esercizi che seguono contengono dei test con gli assert. Per capire come svolgerli, leggi prima Gestione errori e testing

Esercizio - quadrofor

✪✪✪ Restituisce una NUOVA matrice numpy di n righe e n colonne, in cui tutti i valori sono a zero eccetto quelli sui bordi, che devono essere uguali a k

Per esempio, quadro(4, 7.0) deve dare:

array([[7.0, 7.0, 7.0, 7.0],
       [7.0, 0.0, 0.0, 7.0],
       [7.0, 0.0, 0.0, 7.0],
       [7.0, 7.0, 7.0, 7.0]])

Ingredienti:

  • crea una matrice pieni di zeri. ATTENZIONE: quali dimensioni ha? Bisogna usare n o k ? Leggi BENE il testo

Per questa prima versione, prova a riempire le righe e colonne, usando opportuni for in range e scrivendo direttamente nelle singole celle

Mostra soluzione
[1]:

import numpy as np def quadrofor(n, k): raise Exception('TODO IMPLEMENT ME !') r1 = np.array( [[7.0, 7.0, 7.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 7.0, 7.0, 7.0]]) # all_close ritorna True se tutti i valori nella prima matrice sono abbastanza vicini # (cioè entro una certa tolleranza) ai corrispondenti nella seconda assert np.allclose(quadrofor(4, 7.0), r1) r2 = np.array( [ [7.0] ]) assert np.allclose(quadrofor(1, 7.0), r2) r3 = np.array( [ [7.0, 7.0], [7.0, 7.0]]) assert np.allclose(quadrofor(2, 7.0), r3)

Esercizio - quadroslices

✪✪✪ Risolvi l’esercizio precedente, questa volta usando 4 slice

  • NON usare cicli for o while

Mostra soluzione
[2]:

import numpy as np def quadroslices(n, k): raise Exception('TODO IMPLEMENT ME !') r1 = np.array( [[7.0, 7.0, 7.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 7.0, 7., 7.0]]) # all_close ritorna True se tutti i valori nella prima matrice sono abbastanza vicini # (cioè entro una certa tolleranza) ai corrispondenti nella seconda assert np.allclose(quadroslices(4, 7.0), r1) r2 = np.array( [ [7.0] ]) assert np.allclose(quadroslices(1, 7.0), r2) r3 = np.array( [ [7.0, 7.0], [7.0, 7.0]]) assert np.allclose(quadroslices(2, 7.0), r3)

Esercizio - quadroriemp

✪✪✪ Risolvi l’esercizio precedente, questa volta usando np.full e una sola slice

  • NON usare cicli for o while

Mostra soluzione
[3]:

import numpy as np def quadroriemp(n, k): raise Exception('TODO IMPLEMENT ME !') r1 = np.array( [[7.0, 7.0, 7.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 0.0, 0.0, 7.0], [7.0, 7.0, 7., 7.0]]) # all_close ritorna True se tutti i valori nella prima matrice sono abbastanza vicini # (cioè entro una certa tolleranza) ai corrispondenti nella seconda assert np.allclose(quadroriemp(4, 7.0), r1) r2 = np.array( [ [7.0] ]) assert np.allclose(quadroriemp(1, 7.0), r2) r3 = np.array( [ [7.0, 7.0], [7.0, 7.0]]) assert np.allclose(quadroriemp(2, 7.0), r3)

Esercizio - media_righe

✪✪✪ Prende una matrice Numpy n x m e RITORNA una NUOVA matrice numpy di una sola colonna in cui i valori sono la media dei valori nelle corrispondenti righe della matrice in input

Esempio:

Input: matrice 5x4

3 2 1 4
6 2 3 5
4 3 6 2
4 6 5 4
7 2 9 3

Output: matrice 5x1

(3+2+1+4)/4
(6+2+3+5)/4
(4+3+6+2)/4
(4+6+5+4)/4
(7+2+9+3)/4

Ingredienti versione base (lenta):

  • create una matrice n x 1 da ritornare, riempiendola di zeri

  • visita tutte le celle della matrice originale con due for in range annidati

  • durante la visita, accumula nella matrice da ritornare la somma degli elementi presi da ciascuna riga della matrice originale

  • una volta completata la somma di una riga, puoi dividerla per la dimensione ncolonne della matrice originale

  • ritorna la matrice

Ingredienti versione pro (veloce):

  • prova ad usare il parametro axis e reshape

Mostra soluzione
[4]:
import numpy as np

def media_righe(mat):
    raise Exception('TODO IMPLEMENT ME !')
    return ret

m1 = np.array([  [5.0]  ])
r1 = np.array([  [5.0]  ])
assert np.allclose(media_righe(m1), r1)

m2 = np.array([ [5.0, 3.0] ])
r2 = np.array([ [4.0]  ])
assert np.allclose(media_righe(m2), r2)

m3 = np.array(
    [[3,2,1,4],
     [6,2,3,5],
     [4,3,6,2],
     [4,6,5,4],
     [7,2,9,3]])

r3 = np.array([ [(3+2+1+4)/4],
                [(6+2+3+5)/4],
                [(4+3+6+2)/4],
                [(4+6+5+4)/4],
                [(7+2+9+3)/4] ])

assert np.allclose(media_righe(m3), r3)
Mostra soluzione
[5]:
#SOLUZIONE EFFICIENTE media_righe_pro
import numpy as np


Esercizio - matrot

✪✪✪ RITORNA una NUOVA matrice numpy che ha i numeri della matrice numpy di input ruotati di una colonna.

Per ruotati intendiamo che:

  • se un numero nella matrice di input si trova alla colonna j, nella matrice di output si troverà alla colonna j+1 nella stessa riga.

  • Se un numero si trova nell’ultima colonna, nella matrice di output si troverà nella colonna zeresima.

Esempio:

Se abbiamo come input:

np.array(   [
                [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]
            ])

Ci aspettiamo come output:

np.array(   [
                [0,0,1],
                [0,1,1],
                [0,0,0],
                [1,0,1]
            ])
Mostra soluzione
[6]:
import numpy as np

def matrot(matrice):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array(  [ [1] ])
r1 = np.array( [  [1]  ])
assert np.allclose(matrot(m1), r1)

m2 = np.array(  [ [0,1] ])
r2 = np.array( [ [1,0] ])
assert np.allclose(matrot(m2), r2)

m3 = np.array([ [0,1,0] ])
r3 = np.array([ [0,0,1] ])
assert np.allclose(matrot(m3), r3)

m4 = np.array(  [[0,1,0],
                 [1,1,0]])
r4 = np.array(  [[0,0,1],
                 [0,1,1]])
assert np.allclose(matrot(m4), r4)


m5 = np.array([ [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]])
r5 = np.array([ [0,0,1],
                [0,1,1],
                [0,0,0],
                [1,0,1]])
assert np.allclose(matrot(m5), r5)
Mostra soluzione
[7]:
#SOLUZIONE 'PRO'

Esercizio - disp

✪✪✪ Prende una matrice Numpy mat di dimensioninrighe x ncol contenente numeri interi in input e RITORNA una NUOVA matrice numpy di dimensioni nrighe x ncol che è come quella originale, ma nelle celle che contenevano numeri pari adesso ci saranno numero dispari ottenuti sommando 1 al numero pari esistente.

Esempio:

disp(np.array( [
                    [2,5,6,3],
                    [8,4,3,5],
                    [6,1,7,9]
               ]))

Deve dare in output

array([[ 3.,  5.,  7.,  3.],
       [ 9.,  5.,  3.,  5.],
       [ 7.,  1.,  7.,  9.]])

Suggerimenti versione base (lenta):

  • Visto che dovete ritornare una nuova matrice, cominciate con il crearne una vuota

  • scorrete con indici i e j tutta la matrice iniziale

Mostra soluzione
[8]:
import numpy as np

def disp(mat):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array([ [2] ])
r1 = np.array([ [3] ])
assert np.allclose(disp(m1), r1)
assert m1[0][0] == 2  # controlla non si stia modificando la matrice originale

m2 = np.array( [ [2,5,6,3],
                 [8,4,3,5],
                 [6,1,7,9]
               ])
r2 = np.array( [ [3,5,7,3],
                 [9,5,3,5],
                 [7,1,7,9]])
assert np.allclose(disp(m2), r2)


Mostra soluzione
[9]:
#SOLUZIONE EFFICIENTE 1 con np.where


Mostra soluzione
[10]:
#SOLUZIONE veloce 2 senza np.where

Esercizio - radalt

✪✪✪ Prende una matrice numpy mat di dimensioninrighe x ncol contenente numeri interi in input e RITORNA una NUOVA matrice numpy di dimensioni nrighe x ncol, avente alle righe di indice pari i numeri della matrice originale moltiplicati per due, e alle righe di indice dispari gli stessi numeri della matrice originale

Esempio:

m  = np.array( [                      #  indice
                    [ 2, 5, 6, 3],    #    0     pari
                    [ 8, 4, 3, 5],    #    1     dispari
                    [ 7, 1, 6, 9],    #    2     pari
                    [ 5, 2, 4, 1],    #    3     dispari
                    [ 6, 3, 4, 3]     #    4     pari
               ])

Una chiamata a

radalt(m)

ritornerà la matrice numpy

array([[ 4, 10, 12,  6],
       [ 8,  4,  3,  5],
       [14,  2, 12, 18],
       [ 5,  2,  4,  1],
       [12,  6,  8,  6]])
Mostra soluzione
[11]:
import numpy as np

def radalt(mat):
    raise Exception('TODO IMPLEMENT ME !')

# INIZIO TEST: NON TOCCARE !

m1 = np.array([ [2] ])
r1 = np.array([ [4] ])
assert np.allclose(radalt(m1),r1)
assert m1[0][0] == 2  # controlla non si stia modificando la matrice originale

m2 = np.array( [ [ 2, 5, 6],
                 [ 8, 4, 3]])
r2 = np.array( [ [ 4,10,12],
                 [ 8, 4, 3]])
assert np.allclose(radalt(m2), r2)

m3 = np.array( [ [ 2, 5, 6, 3],
                 [ 8, 4, 3, 5],
                 [ 7, 1, 6, 9],
                 [ 5, 2, 4, 1],
                 [ 6, 3, 4, 3] ])
r3 = np.array( [ [ 4,10,12, 6],
                 [ 8, 4, 3, 5],
                 [14, 2,12,18],
                 [ 5, 2, 4, 1],
                 [12, 6, 8, 6] ])
assert np.allclose(radalt(m3), r3)
# FINE TEST
Mostra soluzione
[12]:
#SOLUZIONE EFFICIENTE

Esercizio - scacchiera

✪✪✪ RITORNA una NUOVA matrice numpy di n righe e n colonne, in cui le celle si alternano tra zero e uno.

Esempio: scacchiera(4) deve dare:

array([[1.0, 0.0, 1.0, 0.0],
       [0.0, 1.0, 0.0, 1.0],
       [1.0, 0.0, 1.0, 0.0],
       [0.0, 1.0, 0.0, 1.0]])

Ingredienti versione base (lenta):

  • per alternare, potete usare la range nella forma in cui prende 3 parametri, per esempio range(0,n,2) parte da 0, arriva fino a n escluso e salta di due in due, generando 0,2,4,6,8, …

  • invece range(1,n,2) genererebbe 1,3,5,7, …

Mostra soluzione
[13]:
def scacchiera(n):
    raise Exception('TODO IMPLEMENT ME !')

r1 = np.array( [ [1.0, 0.0, 1.0, 0.0],
                 [0.0, 1.0, 0.0, 1.0],
                 [1.0, 0.0, 1.0, 0.0],
                 [0.0, 1.0, 0.0, 1.0] ])

assert np.allclose(scacchiera(4), r1)

r2 = np.array( [ [1.0] ])
assert np.allclose(scacchiera(1), r2)

r3 = np.array( [ [1.0, 0.0],
                 [0.0, 1.0] ])
assert np.allclose(scacchiera(2), r3)
Mostra soluzione
[14]:
#SOLUZIONE EFFICIENTE


Esercizio - somma_alterna

✪✪✪ MODIFICA la matrice numpy in input (n x n), sommando a tutte le righe dispari le righe pari. Per esempio:

m = [[1.0, 3.0, 2.0, 5.0],
     [2.0, 8.0, 5.0, 9.0],
     [6.0, 9.0, 7.0, 2.0],
     [4.0, 7.0, 2.0, 4.0]]
somma_alterna(m)

adesso m dovrebbe essere :

m = [[1.0, 3.0, 2.0, 5.0],
     [3.0, 11.0,7.0, 14.0],
     [6.0, 9.0, 7.0, 2.0],
     [10.0,16.0,9.0, 6.0]]

Ingredienti versione base (lenta):

  • per alternare, potete usare la range nella forma in cui prende 3 parametri, per esempio range(0,n,2) parte da 0, arriva fino a n escluso e salta di due in due, generando 0,2,4,6,8, …

  • invece range(1,n,2) genererebbe 1,3,5,7, …

Mostra soluzione
[15]:
def somma_alterna(mat):
    raise Exception('TODO IMPLEMENT ME !')


m1 = np.array( [ [1.0, 3.0, 2.0, 5.0],
                 [2.0, 8.0, 5.0, 9.0],
                 [6.0, 9.0, 7.0, 2.0],
                 [4.0, 7.0, 2.0, 4.0] ])

r1 = np.array( [ [1.0, 3.0, 2.0, 5.0],
                 [3.0, 11.0,7.0, 14.0],
                 [6.0, 9.0, 7.0, 2.0],
                 [10.0,16.0,9.0, 6.0] ])

somma_alterna(m1)
assert np.allclose(m1, r1)  # controlla che abbiamo MODIFICATO la matrice originale

m2 = np.array( [ [5.0] ])
r2 = np.array( [ [5.0] ])
somma_alterna(m1)
assert np.allclose(m2, r2)

m3 = np.array( [ [6.0, 1.0],
                 [3.0, 2.0] ])
r3 = np.array( [ [6.0, 1.0],
                 [9.0, 3.0] ])
somma_alterna(m3)
assert np.allclose(m3, r3)
Mostra soluzione
[16]:
#SOLUZIONE EFFICIENTE


Esercizio - media_meta

✪✪✪ Prende in input una matrice numpy con un numero pari di colonne, e RITORNA in output una matrice numpy 1x2: il primo elemento sarà la media della metà sinistra della matrice, il secondo elemento sarà la media della metà destra.

Ingredienti:

  • per ottenere il numero di colonne diviso 2 come numero intero, usare l’operatore //

Mostra soluzione
[17]:
def media_meta(mat):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array([ [7,9] ])

r1 = np.array([(7)/1, (9)/1  ])
assert np.allclose( media_meta(m1), r1)


m2 = np.array([ [3,4],
                [6,3],
                [5,2] ])

r2 = np.array([(3+6+5)/3, (4+3+2)/3  ])
assert np.allclose( media_meta(m2), r2)

m3 = np.array([ [3,2,1,4],
                [6,2,3,5],
                [4,3,6,2],
                [4,6,5,4],
                [7,2,9,3] ])

r3 = np.array([(3+2+6+2+4+3+4+6+7+2)/10, (1+4+3+5+6+2+5+4+9+3)/10  ])

assert np.allclose( media_meta(m3), r3)
Mostra soluzione
[18]:
#SOLUZIONE EFFICIENTE

Esercizio - matxarr

✪✪ Prende una matrice numpy n x m e un ndarray di m elementi, e RITORNA una NUOVA matrice numpy in cui i valori di ogni colonna della matrice di input sono moltiplicati per il corrispondente valore dell’array di n elementi.

Mostra soluzione
[19]:
def matxarr(mat, arr):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array( [ [3,2,1],
                 [6,2,3],
                 [4,3,6],
                 [4,6,5] ] )
a1 = np.array([5, 2, 6])
r1 = np.array([ [3*5, 2*2, 1*6],
                [6*5, 2*2, 3*6],
                [4*5, 3*2, 6*6],
                [4*5, 6*2, 5*6] ])
assert np.allclose(matxarr(m1,a1), r1)
Mostra soluzione
[20]:
#SOLUZIONE EFFICIENTE

Esercizio - colgap

✪✪ Data una matrice numpy di \(n\) righe ed \(m\) colonne, RITORNA un vettore numpy di \(m\) elementi avente la differenza tra i massimi e i minimi di ciascuna colonna.

Esempio:

m = np.array([[5,4,2],
              [8,5,1],
              [6,7,9],
              [3,6,4],
              [4,3,7]])
>>> colgap(m)
array([5, 4, 8])

perchè

5 = 8 - 3
4 = 7 - 3
8 = 9 - 1
Mostra soluzione
[21]:
import numpy as np

def colgap(mat):
    raise Exception('TODO IMPLEMENT ME !')

# TEST
m1 = np.array([[6]])
assert np.allclose(colgap(m1), np.array([0]))
ret = colgap(m1)
assert type(ret) == np.ndarray

m2 = np.array([[6,8]])
assert np.allclose(colgap(m2), np.array([0,0]))
m3 = np.array([[2],
               [5]])

assert np.allclose(colgap(m3), np.array([3]))
m4 = np.array([[5,7],
               [2,9]])
assert np.allclose(colgap(m4), np.array([3,2]))
m5 = np.array([[4,7],
               [4,9]])
assert np.allclose(colgap(m5), np.array([0,2]))
m6 = np.array([[5,2],
               [3,7],
               [9,0]])
assert np.allclose(colgap(m6), np.array([6,7]))
m7 = np.array([[5,4,2],
               [8,5,1],
               [6,7,9],
               [3,6,4],
               [4,3,7]])
assert np.allclose(colgap(m7), np.array([5,4,8]))
Mostra soluzione
[22]:
#SOLUZIONE EFFICIENTE

Esercizio - sostmax

✪✪ Data una matrice numpy mat \(n\) x \(m\), MODIFICA la matrice sostituendo ogni cella con il valore massimo trovato nella colonna corrispondente.

Esempio:

m  = np.array([[5,4,2],
               [8,5,1],
               [6,7,9],
               [3,6,4],
               [4,3,7]])
>>> sostmax(m)    # non ritorna niente!
>>> m
np.array([[8, 7, 9],
          [8, 7, 9],
          [8, 7, 9],
          [8, 7, 9],
          [8, 7, 9]])
Mostra soluzione
[23]:

import numpy as np def sostmax(mat): raise Exception('TODO IMPLEMENT ME !') # TEST m1 = np.array([[6]]) sostmax(m1) assert np.allclose(m1, np.array([6])) ret = sostmax(m1) assert ret == None # non ritorna nulla! m2 = np.array([[6,8]]) sostmax(m2) assert np.allclose(m2, np.array([6,8])) m3 = np.array([[2], [5]]) sostmax(m3) assert np.allclose(m3, np.array([[5], [5]])) m4 = np.array([[5,7], [2,9]]) sostmax(m4) assert np.allclose(m4, np.array([[5,9], [5,9]])) m5 = np.array([[4,7], [4,9]]) sostmax(m5) assert np.allclose(m5, np.array([[4,9], [4,9]])) m6 = np.array([[5,2], [3,7], [9,0]]) sostmax(m6) assert np.allclose(m6, np.array([[9,7], [9,7], [9,7]])) m7 = np.array([[5,4,2], [8,5,1], [6,7,9], [3,6,4], [4,3,7]]) sostmax(m7) assert np.allclose(m7, np.array([[8, 7, 9], [8, 7, 9], [8, 7, 9], [8, 7, 9], [8, 7, 9]]))
Mostra soluzione
[24]:
#SOLUZIONE EFFICIENTE

Esercizio - quadranti

✪✪✪ Data una matrice 2n * 2n, dividere la matrice in 4 parti quadrate uguali (vedi esempio per capire meglio) e RESTITUIRE una NUOVA matrice 2 * 2 contente la media di ogni quadrante

Si assume che la matrice sia sempre di dimensioni pari

SUGGERIMENTO: per dividere per 2 e ottenere un numero intero, usare l’operatore //

Esempio:

1, 2 , 5 , 7
4, 1 , 8 , 0
2, 0 , 5 , 1
0, 2 , 1 , 1

si divide in

  1, 2 | 5 , 7
  4, 1 | 8 , 0
-----------------
  2, 0 | 5 , 1
  0, 2 | 1 , 1

e si restituisce

(1+2+4+1)/ 4  | (5+7+8+0)/4                 2.0 , 5.0
-----------------------------     =>        1.0 , 2.0
(2+0+0+2)/4   | (5+1+1+1)/4
Mostra soluzione
[25]:
import numpy as np

def quadranti(matrice):
    raise Exception('TODO IMPLEMENT ME !')


m1 = np.array( [ [3.0, 5.0],
                 [4.0, 9.0] ])
r1 = np.array([  [3.0, 5.0],
                 [4.0, 9.0],
              ])
assert np.allclose(quadranti(m1),r1)

m2 = np.array( [ [1.0, 2.0 , 5.0 , 7.0],
                 [4.0, 1.0 , 8.0 , 0.0],
                 [2.0, 0.0 , 5.0 , 1.0],
                 [0.0, 2.0 , 1.0 , 1.0] ])
r2 = np.array( [ [2.0, 5.0],
                 [1.0, 2.0] ] )
assert np.allclose(quadranti(m2),r2)
Mostra soluzione
[26]:
#SOLUZIONE EFFICIENTE

Esercizio - scendisali

✪✪✪ Scrivi una funzione che date le dimensioni di n righe e m colonne RITORNA una NUOVA matrice numpy n x m con sequenze che scendono e salgono a righe alterne come negli esempi

  • se m è dispari, lancia ValueError

>>> scendisali(6,10)
array([[0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
       [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
       [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
       [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.]])
Mostra soluzione
[27]:
import numpy as np

def scendisali(n,m):
    raise Exception('TODO IMPLEMENT ME !')


assert np.allclose(scendisali(2,2),  np.array([[0., 0.],
                                               [0., 0.]]))
assert type(scendisali(2,2)) == np.ndarray

assert np.allclose(scendisali(2,6),  np.array([[0., 0., 0., 2., 1., 0.],
                                               [0., 1., 2., 0., 0., 0.]]))

assert np.allclose(scendisali(6,10), np.array([[0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
                                               [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.],
                                               [0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
                                               [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.],
                                               [0., 0., 0., 0., 0., 4., 3., 2., 1., 0.],
                                               [0., 1., 2., 3., 4., 0., 0., 0., 0., 0.]]))
try:
    scendisali(2,3)
    raise Exception("Avrei dovuto fallire prima!")
except ValueError:
    pass
Mostra soluzione
[28]:
#SOLUZIONE EFFICIENTE (SUGGERIMENTO: usare np.tile)

Esercizio - gradini

✪✪✪ Data una matrice quadrata numpy mat di dimensione n, RITORNA un NUOVO array numpy contenente i valori recuperati dalla matrice nell’ordine seguente:

1,2,*,*,*
*,3,4,*,*
*,*,5,6,*
*,*,*,7,8
*,*,*,*,9
  • se la matrice non è quadrata, lancia ValueError

  • NON usare liste python!

  • SUGGERIMENTO: quanti elementi deve avere l’array da ritornare? Lo puoi stabilire a priori?

Esempio:

>>> gradini(np.array([ [6,3,5,2,5],
                       [3,4,2,3,4],
                       [6,5,4,5,1],
                       [4,3,2,3,9],
                       [2,5,1,6,7] ] ))
array([6., 3., 4., 2., 4., 5., 3., 9., 7.])
Mostra soluzione
[29]:
import numpy as np


def gradini(mat):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array([ [7] ])
assert np.allclose(gradini(m1), np.array([7]))
assert type(m1) == np.ndarray

m2 = np.array([ [6,8],
                [9,3]])
assert np.allclose(gradini(m2), np.array([6,8,3]))
assert type(m1) == np.ndarray

m3 = np.array([ [6,3,5,2,5],
                [3,4,2,3,4],
                [6,5,4,5,1],
                [4,3,2,3,9],
                [2,5,1,6,7]])

assert np.allclose(gradini(m3), np.array([6,3,4,2,4,5,3,9,7]))

try:
    gradini(np.array([[1,2,3],
                      [4,5,6]]))
    raise Exception("Avrei dovuto fallire prima!")
except ValueError:
    pass
Mostra soluzione
[30]:
#SOLUZIONE EFFICIENTE

Esercizio - scalivert

✪✪✪ Dato un numero di righe n e un numero di colonne m, RITORNA una NUOVA matrice numpy n x m avente i numeri nelle colonne pari in progressione crescente da 1 a n e nelle colonne dispari decrescente da n a 1

Mostra soluzione
[31]:
import numpy as np

def scalivert(n,m):
    raise Exception('TODO IMPLEMENT ME !')


assert np.allclose(scalivert(1,1), np.array([ [1] ]))
assert np.allclose(scalivert(1,2), np.array([ [1,1] ]))
assert np.allclose(scalivert(2,1), np.array([ [1],
                                              [2]]))
assert np.allclose(scalivert(2,2), np.array([ [1,2],
                                              [2,1]]))
assert type(scalivert(2,2)) == np.ndarray
assert np.allclose(scalivert(4,5), np.array([ [1,4,1,4,1],
                                              [2,3,2,3,2],
                                              [3,2,3,2,3],
                                              [4,1,4,1,4]]))
Mostra soluzione
[32]:
#SOLUZIONE EFFICIENTE (SUGGERIMENTO: usare np.tile)


Esercizio - compricol

✪✪✪ Data una matrice mat \(n\) x \(2m\) con numero di colonne pari, RITORNA una NUOVA matrice \(n\) x \(m\) in cui le colonne sono date dalle somma delle coppie di colonne corrispondenti di mat

  • se mat non ha numero di colonne pari, lancia ValueError

Esempio:

m  = np.array([[5,4,2,6,4,2],
               [7,5,1,0,6,1],
               [6,7,9,2,3,7],
               [5,2,4,6,1,3],
               [7,2,3,4,2,5]])

>>> compricol(m)
np.array([[ 9, 8, 6],
          [12, 1, 7],
          [13,11,10],
          [ 7,10, 4],
          [ 9, 7, 7]])

perchè

9 = 5 + 4     8 = 2 + 6     6 = 4 + 2
12= 7 + 5     1 = 1 + 0     7 = 6 + 1
. . .
Mostra soluzione
[33]:
import numpy as np

def compricol(mat):
    raise Exception('TODO IMPLEMENT ME !')

m1 = [[7,9]]
res = compricol(np.array(m1))
assert type(res) == np.ndarray
assert np.allclose(res, np.array([[16]]))

m2  = np.array([[5,8],
               [7,2]])
assert np.allclose(compricol(m2), np.array([[13],
                                            [9]]))
assert np.allclose(m2, np.array([[5,8],
                                 [7,2]]))  # non cambia la matrice originale

m3  = np.array([[5,4,2,6,4,2],
                [7,5,1,0,6,1],
                [6,7,9,2,3,7],
                [5,2,4,6,1,3],
                [7,2,3,4,2,5]])

assert np.allclose(compricol(m3), np.array([[ 9, 8, 6],
                                            [12, 1, 7],
                                            [13,11,10],
                                            [ 7,10, 4],
                                            [ 9, 7, 7]]))

try:
    compricol(np.array([[7,1,6],
                        [5,2,4]]))
    raise Exception("Avrei dovuto fallire!")
except ValueError:
    pass

Esercizio - revtriang

✪✪✪ Data una matrice quadrata numpy, RITORNA una NUOVA matrice numpy avente le stesse dimensioni dell’originale e i numeri nelle righe della parte triangolare inferiore (diagonale esclusa) in ordine inverso

  • se la matrice non è quadrata, lancia ValueError

Esempio:

m  = np.array([ [5,4,2,6,4],
                [3,5,1,0,6],
                [6,4,9,2,3],
                [5,2,8,6,1],
                [7,9,3,2,2] ])

>>> revtriang(m)
np.array([ [5, 4, 2, 6, 4],
           [3, 5, 1, 0, 6],     # 3       -> 3
           [4, 6, 9, 2, 3],     # 6,4     -> 4,6
           [8, 2, 5, 6, 1],     # 5,2,8   -> 8,2,5
           [2, 3, 9, 7, 2] ])   # 7,9,3,2 -> 2,3,9,7
Mostra soluzione
[34]:
import numpy as np

def revtriang(mat):
    raise Exception('TODO IMPLEMENT ME !')

m1 = np.array([[8]])
assert np.allclose(revtriang(m1), np.array([[8]]))


m3 = np.array([[1,5],
               [9,6]])
assert np.allclose(revtriang(m3), np.array([[1,5],
                                            [9,6]]))

m4 = np.array([[1,5,8],
               [9,6,2],
               [3,2,5]])
assert np.allclose(revtriang(m4), np.array([[1,5,8],
                                            [9,6,2],
                                            [2,3,5]]))
assert np.allclose(m4, np.array([[1,5,8],
                                 [9,6,2],
                                 [3,2,5]]))  # non cambia l'originale

m5 = np.array([[5,4,2,6,4],
               [3,5,1,0,6],
               [6,4,9,2,3],
               [5,2,8,6,1],
               [7,9,3,2,2]])
assert np.allclose(revtriang(m5), np.array([[5, 4, 2, 6, 4],
                                            [3, 5, 1, 0, 6],
                                            [4, 6, 9, 2, 3],
                                            [8, 2, 5, 6, 1],
                                            [2, 3, 9, 7, 2]]))
try:
    revtriang(np.array([[7,1,6],
                        [5,2,4]]))
    raise Exception("Avrei dovuto fallire!")
except ValueError:
    pass

Esercizio - camminas

✪✪✪ Data una matrice numpy \(n\) x \(m\) con \(m\) dispari, RITORNA un array numpy contenente tutti i numeri trovati lungo il percorso di una S, dal basso verso l’alto.

SUGGERIMENTO: puoi determinare a priori la dimensione dell’array risultante?

Esempio:

m = np.array([[5,8,2,4,6,5,7],
              [7,9,5,8,3,2,2],
              [6,1,8,3,6,6,1],
              [1,5,3,7,9,4,7],
              [1,5,3,2,9,5,4],
              [4,3,8,5,6,1,5]])

deve percorrere, dal basso verso l’alto:

m = np.array([[5,8,2,>,>,>,>],
              [7,9,5,^,3,2,2],
              [6,1,8,^,6,6,1],
              [1,5,3,^,9,4,7],
              [1,5,3,^,9,5,4],
              [>,>,>,^,6,1,5]])

Per ottenere:

>>> camminas(m)
array([4., 3., 8., 5., 2., 7., 3., 8., 4., 6., 5., 7.])
Mostra soluzione
[35]:
import numpy as np

def camminas(mat):
    raise Exception('TODO IMPLEMENT ME !')

# TEST
m1 = np.array([[7]])
assert np.allclose(camminas(m1), np.array([7]))

m2 = np.array([[7,5,2]])
assert np.allclose(camminas(m2), np.array([7,5,2]))

m3 = np.array([[9,3,5,6,0]])
assert np.allclose(camminas(m3), np.array([9,3,5,6,0]))

m4 = np.array([[7,5,2],
               [9,3,4]])
assert np.allclose(camminas(m4), np.array([9,3,5,2]))

m5 = np.array([[7,4,6],
               [8,2,1],
               [0,5,3]])
assert np.allclose(camminas(m5), np.array([0,5,2,4,6]))

m6 = np.array([[5,8,2,4,6,5,7],
               [7,9,5,8,3,2,2],
               [6,1,8,3,6,6,1],
               [1,5,3,7,9,4,7],
               [1,5,3,2,9,5,4],
               [4,3,8,5,6,1,5]])
assert np.allclose(camminas(m6), np.array([4,3,8,5,2,7,3,8,4,6,5,7]))

Esercizio - camminaz

✪✪✪ Data una matrice numpy \(n\) x \(m\) con \(m\) dispari, RITORNA un array numpy contenente tutti i numeri trovati lungo il percorso di una Z, dal basso verso l’alto.

SUGGERIMENTO: puoi determinare a priori la dimensione dell’array risultante?

Esempio:

m = np.array([[5,8,2,4,6,5,7],
              [7,9,5,8,3,2,2],
              [6,1,8,3,6,6,1],
              [1,5,3,7,9,4,7],
              [1,5,3,2,9,5,4],
              [4,3,8,5,6,1,5]])

deve percorrere, dal basso verso l’alto:

m = np.array([[<,<,<,^,6,5,7],
              [7,9,5,^,3,2,2],
              [6,1,8,^,6,6,1],
              [1,5,3,^,9,4,7],
              [1,5,3,^,9,5,4],
              [4,3,8,^,<,<,<]])

Per ottenere:

>>> camminaz(m)
array([5.,1.,6.,5.,2.,7.,3.,8.,4.,2.,8.,5.])
Mostra soluzione
[36]:
import numpy as np

def camminaz(mat):
    raise Exception('TODO IMPLEMENT ME !')

# TEST
m1 = np.array([[7]])
assert np.allclose(camminaz(m1), np.array([7]))

m2 = np.array([[7,5,2]])
assert np.allclose(camminaz(m2), np.array([2,5,7]))

m3 = np.array([[9,3,5,6,0]])
assert np.allclose(camminaz(m3), np.array([0,6,5,3,9]))

m4 = np.array([[7,5,2],
               [9,3,4]])
assert np.allclose(camminaz(m4), np.array([4,3,5,7]))

m5 = np.array([[7,4,6],
               [8,2,1],
               [0,5,3]])
assert np.allclose(camminaz(m5), np.array([3,5,2,4,7]))

m6 = np.array([[5,8,2,4,6,5,7],
               [7,9,5,8,3,2,2],
               [6,1,8,3,6,6,1],
               [1,5,3,7,9,4,7],
               [1,5,3,2,9,5,4],
               [4,3,8,5,6,1,5]])
assert np.allclose(camminaz(m6), np.array([5,1,6,5,2,7,3,8,4,2,8,5]))

Prosegui