diff --git a/source/Dive_into_Functions.rst b/source/Dive_into_Functions.rst index 417f5a428bd6ea6ec74f47fbd436d5cb420d86c6..427a4877e8c51595f85ea6bef6a510f829d48fb6 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 0000000000000000000000000000000000000000..bae22e6b4857ad48581ab65dd96fa11028e96bc0 --- /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))