From 9f3fb067ac3b66ee82c3f19a84cc9df25e73618e Mon Sep 17 00:00:00 2001
From: Blaise Li <blaise.li__git@nsup.org>
Date: Tue, 15 Jun 2021 19:42:11 +0200
Subject: [PATCH] Add dict-based matrix solution.
---
source/Dive_into_Functions.rst | 9 ++
source/_static/code/matrix3.py | 272 +++++++++++++++++++++++++++++++++
2 files changed, 281 insertions(+)
create mode 100644 source/_static/code/matrix3.py
diff --git a/source/Dive_into_Functions.rst b/source/Dive_into_Functions.rst
index 417f5a4..427a487 100644
--- a/source/Dive_into_Functions.rst
+++ b/source/Dive_into_Functions.rst
@@ -513,3 +513,12 @@ Second implementation
:language: python
:download:`matrix2.py <_static/code/matrix2.py>` .
+
+
+Thirs implementation
+
+.. literalinclude:: _static/code/matrix3.py
+ :linenos:
+ :language: python
+
+:download:`matrix3.py <_static/code/matrix3.py>` .
diff --git a/source/_static/code/matrix3.py b/source/_static/code/matrix3.py
new file mode 100644
index 0000000..bae22e6
--- /dev/null
+++ b/source/_static/code/matrix3.py
@@ -0,0 +1,272 @@
+"""
+Implementation of simple matrix
+"""
+
+
+def create(nb_rows, nb_cols, val=None):
+ """
+ :param nb_rows: the number of rows
+ :type nb_rows: int
+ :param nb_cols: the number of columns
+ :type nb_cols: int
+ :param val: the default value to fill the matrix
+ :type val: any (None by default)
+ :return: matrix of nb_rows x nb_cols
+ :rtype: matrix
+ """
+ matrix = {}
+ for i in range(nb_rows):
+ for j in range(nb_cols):
+ matrix[(i, j)] = val
+ return matrix
+
+
+import sys
+major, minor = sys.version_info[:2]
+if major < 3 or (major == 3 and minor < 7):
+ raise NotImplementedError(
+ "Implementation missing for this Python version:"
+ "{}.{}".format(major, minor))
+else:
+ def size(matrix):
+ """
+ :param matrix: the matrix of which we want the size
+ :type matrix: matrix
+ :return: the size of matrix (number of rows, number of cols)
+ :rtype: typle of 2 int
+ """
+ # Not robust, and needs a Python version where dicts preserve
+ # key insertion order.
+ # Only works because matrix was created
+ # using a dict where the last inserted key corresponded
+ # to the the last row and last column
+ (last_row, last_col) = list(matrix.keys())[-1]
+ return (last_row + 1, last_col + 1)
+
+
+def _check_bounds(matrix, row, col):
+ """
+ Check whether row and col are compatible with the matrix size.
+
+ :param matrix: the matrix to check
+ :type matrix: matrix
+ :param row: the index of row to check
+ :type row: int
+ :param col: the index of column to check
+ :type col: int
+ :raise: IndexError if row or col are out of matrix bounds
+ """
+ (nb_rows, nb_cols) = size(matrix)
+ if (row < 0 or row >= nb_rows) or (col < 0 or col >= nb_cols):
+ raise IndexError("matrix index out of range")
+
+
+def get_cell(matrix, row, col):
+ """
+ :param matrix: the matrix
+ :type matrix: matrix
+ :param row: the row number
+ :type row: int
+ :param col: the column number
+ :type col: int
+ :return: the content of cell corresponding to row x col
+ :rtype: any
+ """
+ _check_bounds(matrix, row, col)
+ return matrix[(row, col)]
+
+
+def set_cell(matrix, row, col, val):
+ """
+ Set the value val in cell specified by row x col.
+
+ :param matrix: the matrix to modify
+ :type matrix: matrix
+ :param row: the row number of cell to set
+ :type row: int
+ :param col: the column number of cell to set
+ :type col: int
+ :param val: the value to set in cell
+ :type val: int
+ """
+ _check_bounds(matrix, row, col)
+ matrix[(row, col)] = val
+
+
+def mult(matrix, val):
+ """
+ :param matrix: the matrix
+ :type matrix: matrix
+ :param val: the value to mult the matrix with
+ :type val: int
+ :return: a new matrix corresponding the scalar product of matrix * val
+ :rtype: matrix
+ """
+ new_matrix = []
+ for (coords, value) in matrix.items():
+ new_matrix[coords] = value * val
+ return new_matrix
+
+
+def mult_inplace(matrix, val):
+ """
+ Compute the scalar product of a matrix and a value
+ do this operation in place
+
+ :param matrix: the matrix
+ :type matrix: matrix
+ :param val: the value to mult the matrix with
+ :type val: int
+ """
+ for (coords, value) in matrix.items():
+ matrix[coords] = value * val
+
+
+def get_row(matrix, row):
+ """
+ :param matrix: the matrix
+ :type matrix: matrix
+ :param row: row number
+ :type row: int
+ :return: the row of matrix corresponding to row
+ :rtype: list
+ """
+ _check_bounds(matrix, row, 0)
+ _, nb_cols = size(matrix)
+ row_values = []
+ for col in range(nb_cols):
+ row_values.append(get_cell(matrix, row, col))
+ return row_values
+
+
+def set_row(matrix, row, val):
+ """
+ set all cells of row row with val
+
+ :param matrix: the matrix to modify
+ :type matrix: matrix
+ :param row: the row number
+ :type row: int
+ :param val: the value to put in cells
+ :type val: any
+ """
+ _check_bounds(matrix, row, 0)
+ _, nb_cols = size(matrix)
+ for col in range(nb_cols):
+ set_cell(matrix, row, col, val)
+
+
+def get_col(matrix, col):
+ """
+ :param matrix: the matrix
+ :type matrix: matrix
+ :param col: the column number
+ :type col: int
+ :return: the column corresponding to col of matrix
+ a shallow copy of the col
+ :rtype: list
+ """
+ _check_bounds(matrix, 0, col)
+ nb_rows, _ = size(matrix)
+ col_values = []
+ for row in range(nb_rows):
+ col_values.append(get_cell(matrix, row, col))
+ return col_values
+
+
+def set_col(matrix, col, val):
+ """
+ set all cells of col col with val
+
+ :param matrix: the matrix to modify
+ :type matrix: matrix
+ :param col: the column number
+ :type col: int
+ :param val: the value to put in cells
+ :type val: any
+ """
+ _check_bounds(matrix, 0, col)
+ nb_rows, _ = size(matrix)
+ for row in range(nb_rows):
+ set_cell(matrix, row, col, val)
+
+
+def replace_col(matrix, col, col_values):
+ """
+ replace column col with col_values
+
+ :param matrix: the matrix to modify
+ :type matrix: matrix
+ :param col: the column number to replace
+ :type col: int
+ :param col_values: the list of values to use as replacement of column
+ :type col_values: list
+ """
+ nb_rows, nb_cols = size(matrix)
+ if len(col_values) != nb_rows:
+ raise RuntimeError(
+ f"the size of col_values {len(col_values)} does not fit "
+ f"matrix size {nb_rows} x {nb_cols}")
+ _check_bounds(matrix, 0, col)
+ for row in range(nb_rows):
+ set_cell(matrix, col, row, col_values[row])
+
+
+def replace_row(matrix, row, row_values):
+ """
+ replace row row with row_values
+
+ :param matrix: the matrix to modify
+ :type matrix: matrix
+ :param row: the column number
+ :type row: int
+ :param row: the list of value to use as replacement of row
+ :type row: list
+ """
+ nb_rows, nb_cols = size(matrix)
+ if len(row_values) != nb_cols:
+ raise RuntimeError(
+ f"the size of row_values {len(row_values)} does not fit "
+ f"matrix size {nb_rows} x {nb_cols}")
+ _check_bounds(matrix, row, 0)
+ for col in range(nb_cols):
+ set_cell(matrix, col, row, row_values[col])
+
+
+def to_str(matrix):
+ """
+ :param matrix: the matrix to represent as string
+ :type matrix: matrix
+ :return: a string representation of the matrix
+ :rtype: str
+ """
+ lines = []
+ nb_rows, nb_cols = size(matrix)
+ for row in range(nb_rows):
+ lines.append("\t".join([
+ str(val) for val in get_row(matrix, row)]))
+ return "\n".join(lines)
+
+
+if __name__ == '__main__':
+ m = create(5, 3)
+ print(m)
+ print(to_str(m))
+ set_cell(m, 0, 0, 1)
+ print(m)
+ print(to_str(m))
+ set_cell(m, 0, 2, 2)
+ print(m)
+ print(to_str(m))
+ set_cell(m, 4, 0, 12)
+ print(m)
+ print(to_str(m))
+ set_cell(m, 4, 2, 15)
+ print(m)
+ print(to_str(m))
+ print("get row 0", get_row(m, 0))
+ print("get col 0", get_col(m, 0))
+
+ m2 = create(3, 2, 4)
+ mult_inplace(m2, 2)
+ print(to_str(m2))
--
GitLab