From 46842e8c5b5fc78ced0f38206560deb2b8160a54 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <114707091+rohanr18@users.noreply.github.com> Date: Tue, 4 Oct 2022 23:35:56 +0530 Subject: [PATCH] Add missing type hints in `matrix` directory (#6612) * Update count_islands_in_matrix.py * Update matrix_class.py * Update matrix_operation.py * Update nth_fibonacci_using_matrix_exponentiation.py * Update searching_in_sorted_matrix.py * Update count_islands_in_matrix.py * Update matrix_class.py * Update matrix_operation.py * Update rotate_matrix.py * Update sherman_morrison.py * Update spiral_print.py * Update count_islands_in_matrix.py * formatting * formatting * Update matrix_class.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- matrix/count_islands_in_matrix.py | 7 +- matrix/matrix_class.py | 80 ++++++++++--------- matrix/matrix_operation.py | 34 ++++---- ...h_fibonacci_using_matrix_exponentiation.py | 10 +-- matrix/rotate_matrix.py | 16 ++-- matrix/searching_in_sorted_matrix.py | 4 +- matrix/sherman_morrison.py | 46 +++++------ matrix/spiral_print.py | 64 +++++++++------ 8 files changed, 142 insertions(+), 119 deletions(-) diff --git a/matrix/count_islands_in_matrix.py b/matrix/count_islands_in_matrix.py index ad9c67fb8..00f9e1436 100644 --- a/matrix/count_islands_in_matrix.py +++ b/matrix/count_islands_in_matrix.py @@ -4,12 +4,12 @@ class matrix: # Public class to implement a graph - def __init__(self, row: int, col: int, graph: list): + def __init__(self, row: int, col: int, graph: list[list[bool]]) -> None: self.ROW = row self.COL = col self.graph = graph - def is_safe(self, i, j, visited) -> bool: + def is_safe(self, i: int, j: int, visited: list[list[bool]]) -> bool: return ( 0 <= i < self.ROW and 0 <= j < self.COL @@ -17,7 +17,8 @@ class matrix: # Public class to implement a graph and self.graph[i][j] ) - def diffs(self, i, j, visited): # Checking all 8 elements surrounding nth element + def diffs(self, i: int, j: int, visited: list[list[bool]]) -> None: + # Checking all 8 elements surrounding nth element rowNbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order colNbr = [-1, 0, 1, -1, 1, -1, 0, 1] visited[i][j] = True # Make those cells visited diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 57a2fc45f..305cad0a5 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -1,5 +1,7 @@ # An OOP approach to representing and manipulating matrices +from __future__ import annotations + class Matrix: """ @@ -54,7 +56,9 @@ class Matrix: [6. -12. 6.] [-3. 6. -3.]] >>> print(matrix.inverse()) - None + Traceback (most recent call last): + ... + TypeError: Only matrices with a non-zero determinant have an inverse Determinant is an int, float, or Nonetype >>> matrix.determinant() @@ -101,10 +105,9 @@ class Matrix: [198. 243. 288. 304.] [306. 378. 450. 472.] [414. 513. 612. 640.]] - """ - def __init__(self, rows): + def __init__(self, rows: list[list[int]]): error = TypeError( "Matrices must be formed from a list of zero or more lists containing at " "least one and the same number of values, each of which must be of type " @@ -125,42 +128,43 @@ class Matrix: self.rows = [] # MATRIX INFORMATION - def columns(self): + def columns(self) -> list[list[int]]: return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))] @property - def num_rows(self): + def num_rows(self) -> int: return len(self.rows) @property - def num_columns(self): + def num_columns(self) -> int: return len(self.rows[0]) @property - def order(self): + def order(self) -> tuple[int, int]: return (self.num_rows, self.num_columns) @property - def is_square(self): + def is_square(self) -> bool: return self.order[0] == self.order[1] - def identity(self): + def identity(self) -> Matrix: values = [ [0 if column_num != row_num else 1 for column_num in range(self.num_rows)] for row_num in range(self.num_rows) ] return Matrix(values) - def determinant(self): + def determinant(self) -> int: if not self.is_square: - return None + return 0 if self.order == (0, 0): return 1 if self.order == (1, 1): - return self.rows[0][0] + return int(self.rows[0][0]) if self.order == (2, 2): - return (self.rows[0][0] * self.rows[1][1]) - ( - self.rows[0][1] * self.rows[1][0] + return int( + (self.rows[0][0] * self.rows[1][1]) + - (self.rows[0][1] * self.rows[1][0]) ) else: return sum( @@ -168,10 +172,10 @@ class Matrix: for column in range(self.num_columns) ) - def is_invertable(self): + def is_invertable(self) -> bool: return bool(self.determinant()) - def get_minor(self, row, column): + def get_minor(self, row: int, column: int) -> int: values = [ [ self.rows[other_row][other_column] @@ -183,12 +187,12 @@ class Matrix: ] return Matrix(values).determinant() - def get_cofactor(self, row, column): + def get_cofactor(self, row: int, column: int) -> int: if (row + column) % 2 == 0: return self.get_minor(row, column) return -1 * self.get_minor(row, column) - def minors(self): + def minors(self) -> Matrix: return Matrix( [ [self.get_minor(row, column) for column in range(self.num_columns)] @@ -196,7 +200,7 @@ class Matrix: ] ) - def cofactors(self): + def cofactors(self) -> Matrix: return Matrix( [ [ @@ -209,25 +213,27 @@ class Matrix: ] ) - def adjugate(self): + def adjugate(self) -> Matrix: values = [ [self.cofactors().rows[column][row] for column in range(self.num_columns)] for row in range(self.num_rows) ] return Matrix(values) - def inverse(self): + def inverse(self) -> Matrix: determinant = self.determinant() - return None if not determinant else self.adjugate() * (1 / determinant) + if not determinant: + raise TypeError("Only matrices with a non-zero determinant have an inverse") + return self.adjugate() * (1 / determinant) - def __repr__(self): + def __repr__(self) -> str: return str(self.rows) - def __str__(self): + def __str__(self) -> str: if self.num_rows == 0: return "[]" if self.num_rows == 1: - return "[[" + ". ".join(self.rows[0]) + "]]" + return "[[" + ". ".join(str(self.rows[0])) + "]]" return ( "[" + "\n ".join( @@ -240,7 +246,7 @@ class Matrix: ) # MATRIX MANIPULATION - def add_row(self, row, position=None): + def add_row(self, row: list[int], position: int | None = None) -> None: type_error = TypeError("Row must be a list containing all ints and/or floats") if not isinstance(row, list): raise type_error @@ -256,7 +262,7 @@ class Matrix: else: self.rows = self.rows[0:position] + [row] + self.rows[position:] - def add_column(self, column, position=None): + def add_column(self, column: list[int], position: int | None = None) -> None: type_error = TypeError( "Column must be a list containing all ints and/or floats" ) @@ -278,18 +284,18 @@ class Matrix: ] # MATRIX OPERATIONS - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, Matrix): raise TypeError("A Matrix can only be compared with another Matrix") return self.rows == other.rows - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __neg__(self): + def __neg__(self) -> Matrix: return self * -1 - def __add__(self, other): + def __add__(self, other: Matrix) -> Matrix: if self.order != other.order: raise ValueError("Addition requires matrices of the same order") return Matrix( @@ -299,7 +305,7 @@ class Matrix: ] ) - def __sub__(self, other): + def __sub__(self, other: Matrix) -> Matrix: if self.order != other.order: raise ValueError("Subtraction requires matrices of the same order") return Matrix( @@ -309,9 +315,11 @@ class Matrix: ] ) - def __mul__(self, other): + def __mul__(self, other: Matrix | int | float) -> Matrix: if isinstance(other, (int, float)): - return Matrix([[element * other for element in row] for row in self.rows]) + return Matrix( + [[int(element * other) for element in row] for row in self.rows] + ) elif isinstance(other, Matrix): if self.num_columns != other.num_rows: raise ValueError( @@ -329,7 +337,7 @@ class Matrix: "A Matrix can only be multiplied by an int, float, or another matrix" ) - def __pow__(self, other): + def __pow__(self, other: int) -> Matrix: if not isinstance(other, int): raise TypeError("A Matrix can only be raised to the power of an int") if not self.is_square: @@ -348,7 +356,7 @@ class Matrix: return result @classmethod - def dot_product(cls, row, column): + def dot_product(cls, row: list[int], column: list[int]) -> int: return sum(row[i] * column[i] for i in range(len(row))) diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index 8e5d0f583..576094902 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -4,8 +4,10 @@ Functions for 2D matrix operations from __future__ import annotations +from typing import Any -def add(*matrix_s: list[list]) -> list[list]: + +def add(*matrix_s: list[list[int]]) -> list[list[int]]: """ >>> add([[1,2],[3,4]],[[2,3],[4,5]]) [[3, 5], [7, 9]] @@ -25,7 +27,7 @@ def add(*matrix_s: list[list]) -> list[list]: raise TypeError("Expected a matrix, got int/list instead") -def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: +def subtract(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: """ >>> subtract([[1,2],[3,4]],[[2,3],[4,5]]) [[-1, -1], [-1, -1]] @@ -45,7 +47,7 @@ def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: raise TypeError("Expected a matrix, got int/list instead") -def scalar_multiply(matrix: list[list], n: int | float) -> list[list]: +def scalar_multiply(matrix: list[list[int]], n: int | float) -> list[list[float]]: """ >>> scalar_multiply([[1,2],[3,4]],5) [[5, 10], [15, 20]] @@ -55,7 +57,7 @@ def scalar_multiply(matrix: list[list], n: int | float) -> list[list]: return [[x * n for x in row] for row in matrix] -def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]: +def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: """ >>> multiply([[1,2],[3,4]],[[5,5],[7,5]]) [[19, 15], [43, 35]] @@ -77,7 +79,7 @@ def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]: ] -def identity(n: int) -> list[list]: +def identity(n: int) -> list[list[int]]: """ :param n: dimension for nxn matrix :type n: int @@ -89,7 +91,9 @@ def identity(n: int) -> list[list]: return [[int(row == column) for column in range(n)] for row in range(n)] -def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[list]: +def transpose( + matrix: list[list[int]], return_map: bool = True +) -> list[list[int]] | map[list[int]]: """ >>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS list[list] | map[l raise TypeError("Expected a matrix, got int/list instead") -def minor(matrix: list[list], row: int, column: int) -> list[list]: +def minor(matrix: list[list[int]], row: int, column: int) -> list[list[int]]: """ >>> minor([[1, 2], [3, 4]], 1, 1) [[1]] @@ -117,7 +121,7 @@ def minor(matrix: list[list], row: int, column: int) -> list[list]: return [row[:column] + row[column + 1 :] for row in minor] -def determinant(matrix: list[list]) -> int: +def determinant(matrix: list[list[int]]) -> Any: """ >>> determinant([[1, 2], [3, 4]]) -2 @@ -133,7 +137,7 @@ def determinant(matrix: list[list]) -> int: ) -def inverse(matrix: list[list]) -> list[list] | None: +def inverse(matrix: list[list[int]]) -> list[list[float]] | None: """ >>> inverse([[1, 2], [3, 4]]) [[-2.0, 1.0], [1.5, -0.5]] @@ -157,27 +161,27 @@ def inverse(matrix: list[list]) -> list[list] | None: return scalar_multiply(adjugate, 1 / det) -def _check_not_integer(matrix: list[list]) -> bool: +def _check_not_integer(matrix: list[list[int]]) -> bool: return not isinstance(matrix, int) and not isinstance(matrix[0], int) -def _shape(matrix: list[list]) -> tuple[int, int]: +def _shape(matrix: list[list[int]]) -> tuple[int, int]: return len(matrix), len(matrix[0]) def _verify_matrix_sizes( - matrix_a: list[list], matrix_b: list[list] -) -> tuple[tuple, tuple]: + matrix_a: list[list[int]], matrix_b: list[list[int]] +) -> tuple[tuple[int, int], tuple[int, int]]: shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: raise ValueError( - "operands could not be broadcast together with shape " + f"operands could not be broadcast together with shape " f"({shape[0], shape[1]}), ({shape[2], shape[3]})" ) return (shape[0], shape[2]), (shape[1], shape[3]) -def main(): +def main() -> None: matrix_a = [[12, 10], [3, 9]] matrix_b = [[3, 4], [7, 4]] matrix_c = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]] diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index 341a02e1a..7c964d884 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -16,7 +16,7 @@ We can decrease the n times multiplication by following the divide and conquer a """ -def multiply(matrix_a, matrix_b): +def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: matrix_c = [] n = len(matrix_a) for i in range(n): @@ -30,11 +30,11 @@ def multiply(matrix_a, matrix_b): return matrix_c -def identity(n): +def identity(n: int) -> list[list[int]]: return [[int(row == column) for column in range(n)] for row in range(n)] -def nth_fibonacci_matrix(n): +def nth_fibonacci_matrix(n: int) -> int: """ >>> nth_fibonacci_matrix(100) 354224848179261915075 @@ -54,7 +54,7 @@ def nth_fibonacci_matrix(n): return res_matrix[0][0] -def nth_fibonacci_bruteforce(n): +def nth_fibonacci_bruteforce(n: int) -> int: """ >>> nth_fibonacci_bruteforce(100) 354224848179261915075 @@ -70,7 +70,7 @@ def nth_fibonacci_bruteforce(n): return fib1 -def main(): +def main() -> None: for ordinal in "0th 1st 2nd 3rd 10th 100th 1000th".split(): n = int("".join(c for c in ordinal if c in "0123456789")) # 1000th --> 1000 print( diff --git a/matrix/rotate_matrix.py b/matrix/rotate_matrix.py index f638597ae..c16cdb9a8 100644 --- a/matrix/rotate_matrix.py +++ b/matrix/rotate_matrix.py @@ -8,7 +8,7 @@ https://stackoverflow.com/questions/42519/how-do-you-rotate-a-two-dimensional-ar from __future__ import annotations -def make_matrix(row_size: int = 4) -> list[list]: +def make_matrix(row_size: int = 4) -> list[list[int]]: """ >>> make_matrix() [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] @@ -25,7 +25,7 @@ def make_matrix(row_size: int = 4) -> list[list]: return [[1 + x + y * row_size for x in range(row_size)] for y in range(row_size)] -def rotate_90(matrix: list[list]) -> list[list]: +def rotate_90(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_90(make_matrix()) [[4, 8, 12, 16], [3, 7, 11, 15], [2, 6, 10, 14], [1, 5, 9, 13]] @@ -37,7 +37,7 @@ def rotate_90(matrix: list[list]) -> list[list]: # OR.. transpose(reverse_column(matrix)) -def rotate_180(matrix: list[list]) -> list[list]: +def rotate_180(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_180(make_matrix()) [[16, 15, 14, 13], [12, 11, 10, 9], [8, 7, 6, 5], [4, 3, 2, 1]] @@ -49,7 +49,7 @@ def rotate_180(matrix: list[list]) -> list[list]: # OR.. reverse_column(reverse_row(matrix)) -def rotate_270(matrix: list[list]) -> list[list]: +def rotate_270(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_270(make_matrix()) [[13, 9, 5, 1], [14, 10, 6, 2], [15, 11, 7, 3], [16, 12, 8, 4]] @@ -61,22 +61,22 @@ def rotate_270(matrix: list[list]) -> list[list]: # OR.. transpose(reverse_row(matrix)) -def transpose(matrix: list[list]) -> list[list]: +def transpose(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = [list(x) for x in zip(*matrix)] return matrix -def reverse_row(matrix: list[list]) -> list[list]: +def reverse_row(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = matrix[::-1] return matrix -def reverse_column(matrix: list[list]) -> list[list]: +def reverse_column(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = [x[::-1] for x in matrix] return matrix -def print_matrix(matrix: list[list]) -> None: +def print_matrix(matrix: list[list[int]]) -> None: for i in matrix: print(*i) diff --git a/matrix/searching_in_sorted_matrix.py b/matrix/searching_in_sorted_matrix.py index ae8136149..ddca3b1ce 100644 --- a/matrix/searching_in_sorted_matrix.py +++ b/matrix/searching_in_sorted_matrix.py @@ -2,7 +2,7 @@ from __future__ import annotations def search_in_a_sorted_matrix( - mat: list[list], m: int, n: int, key: int | float + mat: list[list[int]], m: int, n: int, key: int | float ) -> None: """ >>> search_in_a_sorted_matrix( @@ -30,7 +30,7 @@ def search_in_a_sorted_matrix( print(f"Key {key} not found") -def main(): +def main() -> None: mat = [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]] x = int(input("Enter the element to be searched:")) print(mat) diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index 63783c8b4..a0c93f115 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -1,14 +1,18 @@ +from __future__ import annotations + +from typing import Any + + class Matrix: """ Matrix structure. """ - def __init__(self, row: int, column: int, default_value: float = 0): + def __init__(self, row: int, column: int, default_value: float = 0) -> None: """ Initialize matrix with given size and default value. - Example: >>> a = Matrix(2, 3, 1) >>> a @@ -20,7 +24,7 @@ class Matrix: self.row, self.column = row, column self.array = [[default_value for c in range(column)] for r in range(row)] - def __str__(self): + def __str__(self) -> str: """ Return string representation of this matrix. @@ -37,7 +41,7 @@ class Matrix: string_format_identifier = "%%%ds" % (max_element_length,) # Make string and return - def single_line(row_vector): + def single_line(row_vector: list[float]) -> str: nonlocal string_format_identifier line = "[" line += ", ".join(string_format_identifier % (obj,) for obj in row_vector) @@ -47,14 +51,13 @@ class Matrix: s += "\n".join(single_line(row_vector) for row_vector in self.array) return s - def __repr__(self): + def __repr__(self) -> str: return str(self) - def validateIndices(self, loc: tuple): + def validateIndices(self, loc: tuple[int, int]) -> bool: """ Check if given indices are valid to pick element from matrix. - Example: >>> a = Matrix(2, 6, 0) >>> a.validateIndices((2, 7)) @@ -69,11 +72,10 @@ class Matrix: else: return True - def __getitem__(self, loc: tuple): + def __getitem__(self, loc: tuple[int, int]) -> Any: """ Return array[row][column] where loc = (row, column). - Example: >>> a = Matrix(3, 2, 7) >>> a[1, 0] @@ -82,11 +84,10 @@ class Matrix: assert self.validateIndices(loc) return self.array[loc[0]][loc[1]] - def __setitem__(self, loc: tuple, value: float): + def __setitem__(self, loc: tuple[int, int], value: float) -> None: """ Set array[row][column] = value where loc = (row, column). - Example: >>> a = Matrix(2, 3, 1) >>> a[1, 2] = 51 @@ -98,11 +99,10 @@ class Matrix: assert self.validateIndices(loc) self.array[loc[0]][loc[1]] = value - def __add__(self, another): + def __add__(self, another: Matrix) -> Matrix: """ Return self + another. - Example: >>> a = Matrix(2, 1, -4) >>> b = Matrix(2, 1, 3) @@ -123,11 +123,10 @@ class Matrix: result[r, c] = self[r, c] + another[r, c] return result - def __neg__(self): + def __neg__(self) -> Matrix: """ Return -self. - Example: >>> a = Matrix(2, 2, 3) >>> a[0, 1] = a[1, 0] = -2 @@ -143,14 +142,13 @@ class Matrix: result[r, c] = -self[r, c] return result - def __sub__(self, another): + def __sub__(self, another: Matrix) -> Matrix: return self + (-another) - def __mul__(self, another): + def __mul__(self, another: int | float | Matrix) -> Matrix: """ Return self * another. - Example: >>> a = Matrix(2, 3, 1) >>> a[0,2] = a[1,2] = 3 @@ -177,11 +175,10 @@ class Matrix: else: raise TypeError(f"Unsupported type given for another ({type(another)})") - def transpose(self): + def transpose(self) -> Matrix: """ Return self^T. - Example: >>> a = Matrix(2, 3) >>> for r in range(2): @@ -201,7 +198,7 @@ class Matrix: result[c, r] = self[r, c] return result - def ShermanMorrison(self, u, v): + def ShermanMorrison(self, u: Matrix, v: Matrix) -> Any: """ Apply Sherman-Morrison formula in O(n^2). @@ -211,7 +208,6 @@ class Matrix: impossible to calculate. Warning: This method doesn't check if self is invertible. Make sure self is invertible before execute this method. - Example: >>> ainv = Matrix(3, 3, 0) >>> for i in range(3): ainv[i,i] = 1 @@ -243,7 +239,7 @@ class Matrix: # Testing if __name__ == "__main__": - def test1(): + def test1() -> None: # a^(-1) ainv = Matrix(3, 3, 0) for i in range(3): @@ -256,11 +252,11 @@ if __name__ == "__main__": v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5 print(f"u is {u}") print(f"v is {v}") - print(f"uv^T is {u * v.transpose()}") + print("uv^T is %s" % (u * v.transpose())) # Sherman Morrison print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}") - def test2(): + def test2() -> None: import doctest doctest.testmod() diff --git a/matrix/spiral_print.py b/matrix/spiral_print.py index 6f699c1ab..2441f05d1 100644 --- a/matrix/spiral_print.py +++ b/matrix/spiral_print.py @@ -1,19 +1,17 @@ """ This program print the matrix in spiral form. This problem has been solved through recursive way. - Matrix must satisfy below conditions i) matrix should be only one or two dimensional ii) number of column of all rows should be equal """ -from collections.abc import Iterable - -def check_matrix(matrix): +def check_matrix(matrix: list[list[int]]) -> bool: # must be - if matrix and isinstance(matrix, Iterable): - if isinstance(matrix[0], Iterable): + matrix = list(list(row) for row in matrix) + if matrix and isinstance(matrix, list): + if isinstance(matrix[0], list): prev_len = 0 for row in matrix: if prev_len == 0: @@ -29,32 +27,48 @@ def check_matrix(matrix): return result -def spiralPrint(a): +def spiral_print_clockwise(a: list[list[int]]) -> None: + """ + >>> spiral_print_clockwise([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) + 1 + 2 + 3 + 4 + 8 + 12 + 11 + 10 + 9 + 5 + 6 + 7 + """ if check_matrix(a) and len(a) > 0: - matRow = len(a) - if isinstance(a[0], Iterable): - matCol = len(a[0]) + a = list(list(row) for row in a) + mat_row = len(a) + if isinstance(a[0], list): + mat_col = len(a[0]) else: for dat in a: - print(dat), + print(dat) return # horizotal printing increasing - for i in range(0, matCol): - print(a[0][i]), + for i in range(0, mat_col): + print(a[0][i]) # vertical printing down - for i in range(1, matRow): - print(a[i][matCol - 1]), + for i in range(1, mat_row): + print(a[i][mat_col - 1]) # horizotal printing decreasing - if matRow > 1: - for i in range(matCol - 2, -1, -1): - print(a[matRow - 1][i]), + if mat_row > 1: + for i in range(mat_col - 2, -1, -1): + print(a[mat_row - 1][i]) # vertical printing up - for i in range(matRow - 2, 0, -1): - print(a[i][0]), - remainMat = [row[1 : matCol - 1] for row in a[1 : matRow - 1]] - if len(remainMat) > 0: - spiralPrint(remainMat) + for i in range(mat_row - 2, 0, -1): + print(a[i][0]) + remain_mat = [row[1 : mat_col - 1] for row in a[1 : mat_row - 1]] + if len(remain_mat) > 0: + spiral_print_clockwise(remain_mat) else: return else: @@ -64,5 +78,5 @@ def spiralPrint(a): # driver code if __name__ == "__main__": - a = ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]) - spiralPrint(a) + a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + spiral_print_clockwise(a)