Exercises#
Introduction#
Let’s see now some exercises. First ones will be given in two versions: first ones usually adopt for cycles and are thus slow, second ones are denoted ‘pro’ and avoid loops using all the power offered by Numpy. In particular in many cases you can obtain very efficient and compact programs by using slices in smart ways.
import numpy as np
All exercises are functions to implement.
Exercise - frameslices#
✪✪✪ RETURN a NEW Numpy matrix of n
rows and n
columns, in which all the values are zero except those on borders, which must be equal to a given k
.
DO NOT use for
nor while
loops, use slices!
Show code cell source
def frameslices(n, k):
mat = np.zeros((n, n))
mat[0, :] = k
mat[:, 0] = k
mat[:, -1] = k
mat[-1, :] = k
return mat
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 return True if all the values in the first matrix are close enough
# (that is, within a given tolerance) to corresponding values in the second
assert np.allclose(frameslices(4, 7.0), r1)
r2 = np.array([[7.0]])
assert np.allclose(frameslices(1, 7.0), r2)
r3 = np.array([[7.0, 7.0], [7.0, 7.0]])
assert np.allclose(frameslices(2, 7.0), r3)
Exercise - framefill#
✪✪✪ Solve the precious exercise, this using np.full
function and with only one slice
DO NOT use
for
norwhile
loops
Show code cell source
def framefill(n, k):
mat = np.full((n, n), k)
mat[1 : -1, 1 : -1] = 0.0
return mat
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 return True if all the values in the first matrix are close enough
# (that is, within a given tolerance) to corresponding values in the second
assert np.allclose(framefill(4, 7.0), r1)
r2 = np.array([[7.0]])
assert np.allclose(framefill(1, 7.0), r2)
r3 = np.array([[7.0, 7.0], [7.0, 7.0]])
assert np.allclose(framefill(2, 7.0), r3)
Exercise - avg_rows#
✪✪✪ Takes a numpy matrix n x m and RETURN a NEW numpy matrix consisting in a single column in which the values are the average of the values in corresponding rows of input matrix
Example:
Input: 5x4 matrix
3 2 1 4
6 2 3 5
4 3 6 2
4 6 5 4
7 2 9 3
Output: 5x1 matrix
(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
Basic version ingredients (slow)
create a matrix n x 1 to return, filling it with zeros
visit all cells of original matrix with two nested fors
during visit, accumulate in the matrix to return the sum of elements takes from each row of original matrix
once completed the sum of a row, you can divide it by the dimension of columns of original matrix
return the matrix
Pro version (fast):
try using
axis
parameter and reshape
Show code cell source
def avg_rows(mat):
nrows, ncols = mat.shape
ret = np.zeros((nrows, 1))
for i in range(nrows):
for j in range(ncols):
ret[i] += mat[i, j]
ret[i] = ret[i] / ncols
# for brevity we could also write
# ret[i] /= ncols
return ret
def avg_rows_pro(mat):
rows, cols = mat.shape # obtain number of rows and columns
media = np.mean(mat, axis=1) # average for rows
media = media.reshape((rows, 1))
return media
m1 = np.array([[5.0]])
r1 = np.array([[5.0]])
assert np.allclose(avg_rows(m1), r1)
m2 = np.array([[5.0, 3.0]])
r2 = np.array([[4.0]])
assert np.allclose(avg_rows(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(avg_rows(m3), r3)
Exercise - matrot#
✪✪✪ RETURN a NEW Numpy matrix which has the numbers of input matrix rotated by a column.
With rotation we mean that:
if a number of input matrix is found in column
j
, in the output matrix it will be in the columnj+1
in the same row.if a number is found in the last column, in the output matrix it will be in the zertoth column
Show code cell source
def matrot(mat):
ret = np.zeros(mat.shape)
for i in range(mat.shape[0]):
ret[i, 0] = mat[i, -1]
for j in range(1, mat.shape[1]):
ret[i, j] = mat[i, j - 1]
return ret
def matrot_pro(mat):
m = mat.shape[0]
n = mat.shape[1]
ret = np.zeros((m, n))
ret[:, 0] = mat[:, -1]
ret[:, 1:] = mat[:, :-1]
return ret
input = np.array(
[
[0, 1, 0],
[1, 1, 0],
[0, 0, 0],
[0, 1, 1],
]
)
matrot(input)
array([[0., 0., 1.],
[0., 1., 1.],
[0., 0., 0.],
[1., 0., 1.]])
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)
Exercise - odd#
✪✪✪ Takes a Numpy matrix mat
of dimension nrows
by ncols
containing integer numbers and RETURN a NEW Numpy matrix of dimension nrows
by ncols
which is like the original, ma in the cells which contained even numbers now there will be odd numbers obtained by summing 1
to the existing even number.
Basic versions hints (slow):
Since you need to return a matrix, start with creating an empty one
go through the whole input matrix with indices
i
andj
Show code cell source
def odd(mat):
nrows, ncols = mat.shape
ret = np.zeros((nrows, ncols))
for i in range(nrows):
for j in range(ncols):
if mat[i, j] % 2 == 0:
ret[i, j] = mat[i, j] + 1
else:
ret[i, j] = mat[i, j]
return ret
def odd_pro1(mat):
ret = np.array(np.where(mat % 2 == 0, mat + 1, mat))
return ret
def odd_pro2(mat):
ret = mat.copy()
ret[ret % 2 == 0] += 1
return ret
odd(
np.array(
[
[2, 5, 6, 3],
[8, 4, 3, 5],
[6, 1, 7, 9],
]
)
)
array([[3., 5., 7., 3.],
[9., 5., 3., 5.],
[7., 1., 7., 9.]])
m1 = np.array([[2]])
m2 = np.array([[3]])
assert np.allclose(odd(m1), m2)
assert m1[0][0] == 2 # checks we are not modifying original matrix
m3 = np.array(
[
[2, 5, 6, 3],
[8, 4, 3, 5],
[6, 1, 7, 9],
]
)
m4 = np.array(
[
[3, 5, 7, 3],
[9, 5, 3, 5],
[7, 1, 7, 9],
]
)
assert np.allclose(odd(m3), m4)
Exercise - doublealt#
✪✪✪ Takes a Numpy matrix mat
of dimensions nrows
x ncols
containing integer numbers and RETURN a NEW Numpy matrix of dimension nrows
x ncols
having at rows of even index the numbers of original matrix multiplied by two, and at rows of odd index the same numbers as the original matrix.
Show code cell source
def doublealt(mat):
nrows, ncols = mat.shape
ret = np.zeros((nrows, ncols))
for i in range(nrows):
for j in range(ncols):
if i % 2 == 0:
ret[i, j] = mat[i, j] * 2
else:
ret[i, j] = mat[i, j]
return ret
def doublealt_pro(mat):
ret = mat.copy()
ret[::2, :] *= 2
return ret
m = np.array(
[
[2, 5, 6, 3], # 0 even
[8, 4, 3, 5], # 1 odd
[7, 1, 6, 9], # 2 even
[5, 2, 4, 1], # 3 odd
[6, 3, 4, 3], # 4 even
]
)
doublealt(m)
array([[ 4., 10., 12., 6.],
[ 8., 4., 3., 5.],
[14., 2., 12., 18.],
[ 5., 2., 4., 1.],
[12., 6., 8., 6.]])
m1 = np.array([[2]])
m2 = np.array([[4]])
assert np.allclose(doublealt(m1), m2)
assert m1[0][0] == 2 # checks we are not modifying original matrix
m3 = np.array([[2, 5, 6], [8, 4, 3]])
m4 = np.array([[4, 10, 12], [8, 4, 3]])
assert np.allclose(doublealt(m3), m4)
m5 = np.array([[2, 5, 6, 3], [8, 4, 3, 5], [7, 1, 6, 9], [5, 2, 4, 1], [6, 3, 4, 3]])
m6 = 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(doublealt(m5), m6)
Exercise - chessboard#
✪✪✪ RETURN a NEW Numpy matrix of n
rows and n
columns, in which all cells alternate zeros and ones.
Basic version ingredients (slow):
to alternate, you can use
range
in the form in which takes 3 parameters, for examplerange(0,n,2)
starts from 0, arrives ton
excluded by jumping one item at a time, generating 0,2,4,6,8, ….range(1,n,2)
would instead generate 1,3,5,7, …
Show code cell source
def chessboard(n):
mat = np.zeros((n, n))
for i in range(0, n, 2):
for j in range(0, n, 2):
mat[i, j] = 1
for i in range(1, n, 2):
for j in range(1, n, 2):
mat[i, j] = 1
return mat
def chessboard_pro(n):
ret = np.zeros((n, n))
ret[::2, ::2] = 1
ret[1::2, 1::2] = 1
return ret
chessboard(4)
array([[1., 0., 1., 0.],
[0., 1., 0., 1.],
[1., 0., 1., 0.],
[0., 1., 0., 1.]])
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(chessboard(4), r1)
r2 = np.array([[1.0]])
assert np.allclose(chessboard(1), r2)
r3 = np.array([[1.0, 0.0], [0.0, 1.0]])
assert np.allclose(chessboard(2), r3)
Exercise - altsum#
✪✪✪ MODIFY the input Numpy matrix (n x n), by summing to all the odd rows the even rows. For example
Basic version ingredients (slow):
to alternate, you can use
range
in the form in which takes 3 parameters, for examplerange(0,n,2)
starts from 0, arrives ton
excluded by jumping one item at a time, generating 0,2,4,6,8, ….instead
range(1,n,2)
would generate 1,3,5,7, ..
Show code cell source
def altsum(mat):
nrows, ncols = mat.shape
for i in range(1, nrows, 2):
for j in range(0, ncols):
mat[i, j] = mat[i, j] + mat[i - 1, j]
def altsum_pro(mat):
mat[1::2] += mat[::2]
return mat
m = 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],
]
)
altsum(m)
m
array([[ 1., 3., 2., 5.],
[ 3., 11., 7., 14.],
[ 6., 9., 7., 2.],
[10., 16., 9., 6.]])
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],
]
)
altsum(m1)
assert np.allclose(m1, r1) # checks we MODIFIED the original matrix
m2 = np.array([[5.0]])
r2 = np.array([[5.0]])
altsum(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]])
altsum(m3)
assert np.allclose(m3, r3)
Exercise - avg_half#
✪✪✪ Takes as input a Numpy matrix with an even number of columns, and RETURN as output a Numpy matrix 1x2, in which the first element will be the average of the left half of the matrix, and the second element will be the average of the right half.
Ingredients:
to obtain the number of columns divided by two as integer number, use
//
operator
Show code cell source
def avg_half(mat):
nrows, ncols = mat.shape
half_cols = ncols // 2
avg_sx = 0.0
avg_dx = 0.0
for i in range(nrows):
for j in range(half_cols):
avg_sx += mat[i, j]
for j in range(half_cols, ncols):
avg_dx += mat[i, j]
half_elements = nrows * half_cols
avg_sx /= half_elements
avg_dx /= half_elements
return np.array([avg_sx, avg_dx])
def avg_half_pro(mat):
n, m = mat.shape
m2 = m // 2
half_els = n * m2
avg = np.zeros((1, 2))
avg[0, 0] = np.sum(mat[:, :m2]) / half_els
avg[0, 1] = np.sum(mat[:, m2:]) / half_els
return avg
m1 = np.array([[7, 9]])
r1 = np.array([(7) / 1, (9) / 1])
assert np.allclose(avg_half(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(avg_half(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(avg_half(m3), r3)
Exercise - matxarr#
✪✪ Takes a Numpy matrix n
x m
and an ndarray
of m
elements, and RETURN a NEW Numpy matrix in which the values of each column of input matrix are multiplied by the corresponding value in the n
elements array.
Show code cell source
def matxarr(mat, arr):
ret = np.zeros(mat.shape)
for i in range(mat.shape[0]):
for j in range(mat.shape[1]):
ret[i, j] = mat[i, j] * arr[j]
return ret
def matxarr_pro(mat, arr):
return np.array(arr) * mat
m1 = np.array(
[
[3, 2, 1],
[6, 2, 3],
[4, 3, 6],
[4, 6, 5],
]
)
a1 = [5, 2, 6]
r1 = [
[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)
Exercise - colgap#
✪✪ Given a numpy matrix of \(n\) rows and \(m\) columns, RETURN a numpy vector of \(m\) elements consisting in the difference between the maximum and minimum values of each column.
Show code cell source
def colgap(mat):
mx = mat[0].copy()
mn = mat[0].copy()
for i in range(mat.shape[0]):
for j in range(mat.shape[1]):
if mat[i, j] > mx[j]:
mx[j] = mat[i, j]
if mat[i, j] < mn[j]:
mn[j] = mat[i, j]
return mx - mn
def colgap_pro(mat):
mx = np.max(mat, axis=0)
mn = np.min(mat, axis=0)
return mx - mn
m = np.array(
[
[5, 4, 2],
[8, 5, 1],
[6, 7, 9],
[3, 6, 4],
[4, 3, 7],
]
)
colgap(m)
array([5, 4, 8])
m1 = np.array([[6]])
assert np.allclose(colgap(m1), np.array([0]))
ret = colgap(m1)
assert isinstance(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]))
Exercise - substmax#
✪✪ Given an \(n\) x \(m\) numpy matrix mat
, MODIFY the matrix substituting each cell with the maximum value found in the corresponding column.
Show code cell source
def substmax(mat):
mx = mat[0].copy()
for i in range(mat.shape[0]):
for j in range(mat.shape[1]):
if mat[i, j] > mx[j]:
mx[j] = mat[i, j]
for i in range(mat.shape[0]):
for j in range(mat.shape[1]):
mat[i, j] = mx[j]
def substmax_pro(mat):
mat[:, :] = np.max(mat, axis=0)
m = np.array(
[
[5, 4, 2],
[8, 5, 1],
[6, 7, 9],
[3, 6, 4],
[4, 3, 7],
]
)
substmax(m) # returns nothing!
m
array([[8, 7, 9],
[8, 7, 9],
[8, 7, 9],
[8, 7, 9],
[8, 7, 9]])
m1 = np.array([[6]])
substmax(m1)
assert np.allclose(m1, np.array([6]))
ret = substmax(m1)
assert ret is None # returns nothing!
m2 = np.array([[6, 8]])
substmax(m2)
assert np.allclose(m2, np.array([6, 8]))
m3 = np.array([[2], [5]])
substmax(m3)
assert np.allclose(m3, np.array([[5], [5]]))
m4 = np.array([[5, 7], [2, 9]])
substmax(m4)
assert np.allclose(m4, np.array([[5, 9], [5, 9]]))
m5 = np.array([[4, 7], [4, 9]])
substmax(m5)
assert np.allclose(m5, np.array([[4, 9], [4, 9]]))
m6 = np.array(
[
[5, 2],
[3, 7],
[9, 0],
]
)
expected = np.array(
[
[9, 7],
[9, 7],
[9, 7],
]
)
substmax(m6)
assert np.allclose(m6, expected)
m7 = np.array(
[
[5, 4, 2],
[8, 5, 1],
[6, 7, 9],
[3, 6, 4],
[4, 3, 7],
]
)
expected = np.array(
[
[8, 7, 9],
[8, 7, 9],
[8, 7, 9],
[8, 7, 9],
[8, 7, 9],
]
)
substmax(m7)
assert np.allclose(m7, expected)
Exercise - quadrants#
✪✪✪ Given a matrix 2n * 2n
, divide the matrix in 4 equal square parts (see example) and RETURN a NEW matrix 2 * 2
containing the average of each quadrant.
We assume the matrix is always of even dimensions
HINT: to divide by two and obtain an integer number, use //
operator
Example:
1, 2 , 5 , 7
4, 1 , 8 , 0
2, 0 , 5 , 1
0, 2 , 1 , 1
can be divided in
1, 2 | 5 , 7
4, 1 | 8 , 0
-----------------
2, 0 | 5 , 1
0, 2 | 1 , 1
and returns
(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
Show code cell source
def quadrants(mat):
ret = np.zeros((2, 2))
dim = mat.shape[0]
n = dim // 2
elements_per_quad = n * n
for i in range(n):
for j in range(n):
ret[0, 0] += mat[i, j]
ret[0, 0] /= elements_per_quad
for i in range(n, dim):
for j in range(n):
ret[1, 0] += mat[i, j]
ret[1, 0] /= elements_per_quad
for i in range(n, dim):
for j in range(n, dim):
ret[1, 1] += mat[i, j]
ret[1, 1] /= elements_per_quad
for i in range(n):
for j in range(n, dim):
ret[0, 1] += mat[i, j]
ret[0, 1] /= elements_per_quad
return ret
def quadrants_pro(matrice):
m = matrice.shape[0]
ret = np.zeros((2, 2))
n = m // 2
qarea = n * n
ret[0, 0] = np.sum(matrice[:n, :n]) / qarea
ret[0, 1] = np.sum(matrice[:n, n:]) / qarea
ret[1, 0] = np.sum(matrice[n:, :n]) / qarea
ret[1, 1] = np.sum(matrice[n:, n:]) / qarea
return ret
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(quadrants(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(quadrants(m2), r2)
Exercise - downup#
✪✪✪ Write a function which given the dimensions of n
rows and m
columns, RETURN a NEW n
x m
numpy matrix with sequences which go down and up in alternating rows as in the examples.
if
m
is odd, raisesValueError
Show code cell source
def downup(n, m):
if m % 2 == 1:
raise ValueError("m must be even, found %s" % m)
mat = np.zeros((n, m))
for i in range(0, n, 2):
for j in range(m // 2):
mat[i, j + m // 2] = m // 2 - j - 1
for i in range(1, n, 2):
for j in range(m // 2):
mat[i, j] = j
return mat
def downup_pro(n, m):
if m % 2 == 1:
raise ValueError("m must be even, found %s" % m)
ret = np.zeros((n, m))
left = np.tile(np.arange(0.0, m / 2, 1.0), (n // 2, 1))
right = np.tile(np.arange(m / 2 - 1, -0.5, -1.0), (n // 2, 1))
ret[1::2, : m // 2] = left
ret[0::2, m // 2 :] = right
return ret
downup(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.]])
assert np.allclose(downup(2, 2), np.array([[0.0, 0.0], [0.0, 0.0]]))
assert isinstance(downup(2, 2), np.ndarray)
assert np.allclose(
downup(2, 6),
np.array([[0.0, 0.0, 0.0, 2.0, 1.0, 0.0], [0.0, 1.0, 2.0, 0.0, 0.0, 0.0]]),
)
assert np.allclose(
downup(6, 10),
np.array(
[
[0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 3.0, 2.0, 1.0, 0.0],
[0.0, 1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 3.0, 2.0, 1.0, 0.0],
[0.0, 1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 3.0, 2.0, 1.0, 0.0],
[0.0, 1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0],
]
),
)
try:
downup(2, 3)
raise Exception("I should have failed!")
except ValueError:
pass
Exercise - stairsteps#
✪✪✪ Given a numpy square matrix mat
of dimension n
, RETURN a NEW numpy array containing the values retrieved from the matrix in the following order:
1,2,*,*,*
*,3,4,*,*
*,*,5,6,*
*,*,*,7,8
*,*,*,*,9
if the matrix is not square, raises
ValueError
DO NOT use python lists!
HINT: how many elements must the array to return have?
def stairsteps(mat):
n, m = mat.shape
if n != m:
raise ValueError("Required a square matrix, found instead: %s x %s" % (n, m))
res = np.zeros(n + n - 1)
for i in range(n):
res[2 * i] = mat[i, i]
for i in range(n - 1):
res[2 * i + 1] = mat[i, i + 1]
return res
def stairsteps_pro(mat):
n, m = mat.shape
if n != m:
raise ValueError("Richiesta una n x n, trovata invece una %s x %s" % (n, m))
a = np.diag(mat)
b = np.diag(mat, 1)
ret = np.zeros((1, a.shape[0] + b.shape[0]))
ret[:, ::2] = a
ret[:, 1::2] = b
return ret
stairsteps(
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.])
m1 = np.array([[7]])
assert np.allclose(stairsteps(m1), np.array([7]))
assert isinstance(m1, np.ndarray)
m2 = np.array([[6, 8], [9, 3]])
assert np.allclose(stairsteps(m2), np.array([6, 8, 3]))
assert isinstance(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(stairsteps(m3), np.array([6, 3, 4, 2, 4, 5, 3, 9, 7]))
try:
stairsteps(np.array([[1, 2, 3], [4, 5, 6]]))
raise Exception("I should have failed!")
except ValueError:
pass
Exercise - vertstairs#
✪✪✪ Given a numbers of rows n
and of columns m
, RETURN a NEW n
x m
numpy matrix having the numbers in even columns progressively increasing from 1
to n
, and numbers in odd columns progressively decreasing from n
to 1
.
Show code cell source
def vertstairs(n, m):
ret = np.zeros((n, m))
for i in range(n):
for j in range(m):
if j % 2 == 0:
ret[i, j] = i + 1
else:
ret[i, j] = n - i
return ret
def vertstairs_pro(n, m):
ret = np.zeros((n, m))
ret[:, 0::2] = np.tile(np.transpose([np.arange(1, n + 1, 1)]), (m + 1) // 2)
ret[:, 1::2] = np.tile(np.transpose([np.arange(n, 0, -1)]), m // 2)
return ret
assert np.allclose(vertstairs(1, 1), np.array([[1]]))
assert np.allclose(vertstairs(1, 2), np.array([[1, 1]]))
assert np.allclose(vertstairs(2, 1), np.array([[1], [2]]))
assert np.allclose(vertstairs(2, 2), np.array([[1, 2], [2, 1]]))
assert isinstance(vertstairs(2, 2), np.ndarray)
assert np.allclose(
vertstairs(4, 5),
np.array([[1, 4, 1, 4, 1], [2, 3, 2, 3, 2], [3, 2, 3, 2, 3], [4, 1, 4, 1, 4]]),
)
Exercise - comprescol#
✪✪✪ Given an \(n\) x \(2m\) matrix mat
with an even number of columns, RETURN a NEW \(n\) x \(m\) matrix in which the columns are given by the sum of corresponding column pairs from mat
if
mat
doesn’t have an even number of columns, raiseValueError
Example:
>>> >>> comprescol(m)
np.array([[ 9, 8, 6],
[12, 1, 7],
[13,11,10],
[ 7,10, 4],
[ 9, 7, 7]])
because
9 = 5 + 4 8 = 2 + 6 6 = 4 + 2
12= 7 + 5 1 = 1 + 0 7 = 6 + 1
. . .
Show code cell source
def comprescol(mat):
if mat.shape[1] % 2 != 0:
raise ValueError(
"Expected matrix with an even number of columns, got instead %s"
% mat.shape[1]
)
ret = mat[:, ::2].copy()
ret += mat[:, 1::2]
return ret
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],
]
)
comprescol(m)
array([[ 9, 8, 6],
[12, 1, 7],
[13, 11, 10],
[ 7, 10, 4],
[ 9, 7, 7]])
m1 = [[7, 9]]
res = comprescol(np.array(m1))
assert isinstance(res, np.ndarray)
assert np.allclose(res, np.array([[16]]))
m2 = np.array([[5, 8], [7, 2]])
assert np.allclose(comprescol(m2), np.array([[13], [9]]))
assert np.allclose(
m2, np.array([[5, 8], [7, 2]])
) # check doesn't MODIFY original matrix
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(
comprescol(m3),
np.array([[9, 8, 6], [12, 1, 7], [13, 11, 10], [7, 10, 4], [9, 7, 7]]),
)
try:
comprescol(np.array([[7, 1, 6], [5, 2, 4]]))
raise Exception("I should have failed!")
except ValueError:
pass
Exercise - revtriang#
✪✪✪ Givena square numpy matrix, RETURN a NEW numpy matrix having the same dimensions as the original one, and the numbers in the lower triangular part (excluding the diagonal) in reverse.
if the matrix is not square, raise
ValueError
Show code cell source
def revtriang(mat):
n, m = mat.shape
if n != m:
raise ValueError("Expected square matrix, got instead n=%s, m=%s" % (n, m))
ret = mat.copy()
for i in range(1, n):
ret[i, :i] = np.flip(mat[i, :i])
return ret
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)
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]])
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]])
) # shouldn't change the original
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("I should have failed!")
except ValueError:
pass
Exercise - walkas#
✪✪✪ Given a numpy matrix \(n\) x \(m\) with odd \(m\), RETURN a numpy array containing all the numbers found along the path of an S, from bottom to top.
HINT: can you determine the array dimension right away?
Show code cell source
def walkas(mat):
n, m = mat.shape
ret = np.zeros(n + m - 1)
ret[: m // 2] = mat[-1, : m // 2]
ret[m // 2 : m // 2 + n] = mat[::-1, m // 2]
ret[-m // 2 :] = mat[0, m // 2 :]
return ret
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],
]
)
walkas(m)
array([4., 3., 8., 5., 2., 7., 3., 8., 4., 6., 5., 7.])
m1 = np.array([[7]])
assert np.allclose(walkas(m1), np.array([7]))
m2 = np.array([[7, 5, 2]])
assert np.allclose(walkas(m2), np.array([7, 5, 2]))
m3 = np.array([[9, 3, 5, 6, 0]])
assert np.allclose(walkas(m3), np.array([9, 3, 5, 6, 0]))
m4 = np.array([[7, 5, 2], [9, 3, 4]])
assert np.allclose(walkas(m4), np.array([9, 3, 5, 2]))
m5 = np.array([[7, 4, 6], [8, 2, 1], [0, 5, 3]])
assert np.allclose(walkas(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(walkas(m6), np.array([4, 3, 8, 5, 2, 7, 3, 8, 4, 6, 5, 7]))
Exercise - walkaz#
✪✪✪ Given a numpy matrix \(n\) x \(m\) with odd \(m\), RETURN a numpy array containing all the numbers found along the path of an Z, from bottom to top.
HINT: can you determine the array dimension right away?
Show code cell source
def walkaz(mat):
n, m = mat.shape
ret = np.zeros(n + m - 1)
ret[: m // 2] = mat[-1, -1 : m // 2 : -1]
ret[m // 2 : m // 2 + n] = mat[::-1, m // 2]
ret[-m // 2 :] = mat[0, m // 2 :: -1]
return ret
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],
]
)
walkaz(m)
array([5., 1., 6., 5., 2., 7., 3., 8., 4., 2., 8., 5.])
m1 = np.array([[7]])
assert np.allclose(walkaz(m1), np.array([7]))
m2 = np.array([[7, 5, 2]])
assert np.allclose(walkaz(m2), np.array([2, 5, 7]))
m3 = np.array([[9, 3, 5, 6, 0]])
assert np.allclose(walkaz(m3), np.array([0, 6, 5, 3, 9]))
m4 = np.array([[7, 5, 2], [9, 3, 4]])
assert np.allclose(walkaz(m4), np.array([4, 3, 5, 7]))
m5 = np.array([[7, 4, 6], [8, 2, 1], [0, 5, 3]])
assert np.allclose(walkaz(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(walkaz(m6), np.array([5, 1, 6, 5, 2, 7, 3, 8, 4, 2, 8, 5]))
Continue#
Try doing exercises from Nested structures using Numpy instead - try making the exercises performant by using Numpy features and functions (i.e. 2*arr
multiplies all numbers in arr without the need of a slow Python for
)
References#
You can find much more details on Python Data Science Handbook, Numpy part
machinelearningplus has Numpy exercises - (difficulty L1, L2, you can also try L3)