Spoorthi Satheesha

Sporadic writer
Serial anthropomorphizer

Share: 

ZK-Bootcamp - Precourse Practise

Numpy warmup

Make sure you have numpy installed.

    !python -m pip install numpy
Requirement already satisfied: numpy in c:\python312\lib\site-packages (2.3.0)

[notice] A new release of pip is available: 24.2 -> 25.1.1
[notice] To update, run: python.exe -m pip install --upgrade pip
    import numpy as np

Exercise 1, add two arrays together

We have two arrays: A and B

A = [[1,2,3],[4,5,6],[7,8,9]]

B = [[1,1,1],[2,2,2],[3,3,3]]

C = [[2,3,4],[6,7,8],[10,11,12]]

Your code should work for general matrices, not just the ones above. Use np.array, not np.matrix. Your function will need to cast the above to np.arrays. If you get stuck ask chatGPT!

    A = [[1,2,3],[4,5,6],[7,8,9]]
    B = [[1,1,1],[2,2,2],[3,3,3]]
    C = [[2,3,4],[6,7,8],[10,11,12]]
    def add_arrays(A, B):
        # your code here
        for i in range(len(A)): # Iterate through rows
            for j in range(len(A[i])): # Iterate through columns
                    C[i][j] = A[i][j] + B[i][j]
        return C
    assert (add_arrays(A, B) == np.array(C)).all()

What does the .all() do? The above operation does an elementwise equality check. It checks that every item in the array is True.

    print(np.array([True, True, True]).all())
    print(np.array([False, True, True]).all())
True
False

Exercise 2, element-wise and matrix multiplication

When dealing with numpy arrays, we need to be clear if we are doing matrix multiplication or elementwise multiplication.

Your task is to write functions for both. Numpy supports both, figure out how it does it. Don’t implement it manually

    def matrix_multiply(A, B):
        A = np.array(A)
        B = np.array(B)
        C = A @ B  # Using numpy's matrix multiplication
        return C
    R = [[14,14,14],[32,32,32],[50,50,50]]
    assert (matrix_multiply(A, B) == np.array(R)).all()
    def element_wise_multiply(A, B):
        A = np.array(A)
        B = np.array(B)
        C = A * B  # Element-wise multiplication
        return C
    R = [[1,2,3],[8,10,12],[21,24,27]]
    assert (element_wise_multiply(A, B) == np.array(R)).all()

To avoid giving hints, we won’t supply the test case here. But you can check your work online!

Exercise 3, the dot product

The dot product is another kind of multiplication.

We expect [1,2,3,4] $\cdot$ [1,2,3,4] to be equal (1 * 1) + (2 * 2) + (3 * 3) + (4 * 4) = 1 + 4 + 9 + 16 = 20

Figure out numpy’s implementation and do it. Don’t implement it manually.

    def dot_product(A, B):
        A = np.array(A)
        B = np.array(B)
        C = np.dot(A, B)
        return C
    D_A = [1,2,3,4]
    D_B = [1,2,3,4]
    D = 30
    assert (dot_product(D_A, D_B) == D).all()

Exercise 4, linear combinations

A linear combination is a Vector multiplied by a constant plus another Vector multiplied by a constant.

Aa + Bb = C (A, B, C are vectors, a and b are scalars)

Compute the linear combination in the general case.

    def linearCombination(A, B, a, b):
        A = np.array(A)
        B = np.array(B)
        return a * A + b * B
    vector1 = np.array([1,2])
    vector2 = np.array([5,6])
    scalar1 = 3
    scalar2 = 10
    
    assert (np.array([53, 66]) == linearCombination(vector1, vector2, scalar1, scalar2)).all()

Exercise 5, modular arithmetic

Modular arithmetic is important in cryptography. The challenge here is to compute the modular inverse of 15 % 1223. That is 15 * x % 1223 == 1. The basic syntax for this is the same as other languages

    (5 * 16) % 1223
80
    (5 + 1219) % 1223
1

Be very careful, because the mod operator sometimes takes precedence!

    ## Todo: compute x
    x = pow(5, -1, 1223)  # Modular multiplicative inverse of 5 mod 1223
    assert (5 * x )% 1223 == 1

Hint: Python 3.8 has a very nice way to do this

Exercise 6, Column and Row Slicing

Numpy let’s you select rows and columns from matrices. For example, given

[[1,2,3],
 [4,5,6],
 [7,8,9]] 

you can retrive [2,5,8] or [7,8,9] conveniently. Implement those below:

    def get_column_as_1d(A, col_number):
        A = np.array(A)
        return A[:, col_number]  # Return the specified column as a 1D array
    
    def get_row_as_1d(A, col_number):
        A = np.array(A)
        return A[col_number, :]  # Return the specified row as a 1D array
    A = [[1,2,3],[4,5,6],[7,8,9]] 
    print(get_column_as_1d(A, 1)) # [2,5,8]
[2 5 8]
    print(get_row_as_1d(A, 2)) # [7,8,9]
[7 8 9]
,