mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
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>
This commit is contained in:
parent
a84fb58271
commit
46842e8c5b
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
|
|
||||||
class matrix: # Public class to implement a graph
|
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.ROW = row
|
||||||
self.COL = col
|
self.COL = col
|
||||||
self.graph = graph
|
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 (
|
return (
|
||||||
0 <= i < self.ROW
|
0 <= i < self.ROW
|
||||||
and 0 <= j < self.COL
|
and 0 <= j < self.COL
|
||||||
|
@ -17,7 +17,8 @@ class matrix: # Public class to implement a graph
|
||||||
and self.graph[i][j]
|
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
|
rowNbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order
|
||||||
colNbr = [-1, 0, 1, -1, 1, -1, 0, 1]
|
colNbr = [-1, 0, 1, -1, 1, -1, 0, 1]
|
||||||
visited[i][j] = True # Make those cells visited
|
visited[i][j] = True # Make those cells visited
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# An OOP approach to representing and manipulating matrices
|
# An OOP approach to representing and manipulating matrices
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
class Matrix:
|
class Matrix:
|
||||||
"""
|
"""
|
||||||
|
@ -54,7 +56,9 @@ class Matrix:
|
||||||
[6. -12. 6.]
|
[6. -12. 6.]
|
||||||
[-3. 6. -3.]]
|
[-3. 6. -3.]]
|
||||||
>>> print(matrix.inverse())
|
>>> 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
|
Determinant is an int, float, or Nonetype
|
||||||
>>> matrix.determinant()
|
>>> matrix.determinant()
|
||||||
|
@ -101,10 +105,9 @@ class Matrix:
|
||||||
[198. 243. 288. 304.]
|
[198. 243. 288. 304.]
|
||||||
[306. 378. 450. 472.]
|
[306. 378. 450. 472.]
|
||||||
[414. 513. 612. 640.]]
|
[414. 513. 612. 640.]]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, rows):
|
def __init__(self, rows: list[list[int]]):
|
||||||
error = TypeError(
|
error = TypeError(
|
||||||
"Matrices must be formed from a list of zero or more lists containing at "
|
"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 "
|
"least one and the same number of values, each of which must be of type "
|
||||||
|
@ -125,42 +128,43 @@ class Matrix:
|
||||||
self.rows = []
|
self.rows = []
|
||||||
|
|
||||||
# MATRIX INFORMATION
|
# 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]))]
|
return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def num_rows(self):
|
def num_rows(self) -> int:
|
||||||
return len(self.rows)
|
return len(self.rows)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def num_columns(self):
|
def num_columns(self) -> int:
|
||||||
return len(self.rows[0])
|
return len(self.rows[0])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def order(self):
|
def order(self) -> tuple[int, int]:
|
||||||
return (self.num_rows, self.num_columns)
|
return (self.num_rows, self.num_columns)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_square(self):
|
def is_square(self) -> bool:
|
||||||
return self.order[0] == self.order[1]
|
return self.order[0] == self.order[1]
|
||||||
|
|
||||||
def identity(self):
|
def identity(self) -> Matrix:
|
||||||
values = [
|
values = [
|
||||||
[0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
|
[0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
|
||||||
for row_num in range(self.num_rows)
|
for row_num in range(self.num_rows)
|
||||||
]
|
]
|
||||||
return Matrix(values)
|
return Matrix(values)
|
||||||
|
|
||||||
def determinant(self):
|
def determinant(self) -> int:
|
||||||
if not self.is_square:
|
if not self.is_square:
|
||||||
return None
|
return 0
|
||||||
if self.order == (0, 0):
|
if self.order == (0, 0):
|
||||||
return 1
|
return 1
|
||||||
if self.order == (1, 1):
|
if self.order == (1, 1):
|
||||||
return self.rows[0][0]
|
return int(self.rows[0][0])
|
||||||
if self.order == (2, 2):
|
if self.order == (2, 2):
|
||||||
return (self.rows[0][0] * self.rows[1][1]) - (
|
return int(
|
||||||
self.rows[0][1] * self.rows[1][0]
|
(self.rows[0][0] * self.rows[1][1])
|
||||||
|
- (self.rows[0][1] * self.rows[1][0])
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return sum(
|
return sum(
|
||||||
|
@ -168,10 +172,10 @@ class Matrix:
|
||||||
for column in range(self.num_columns)
|
for column in range(self.num_columns)
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_invertable(self):
|
def is_invertable(self) -> bool:
|
||||||
return bool(self.determinant())
|
return bool(self.determinant())
|
||||||
|
|
||||||
def get_minor(self, row, column):
|
def get_minor(self, row: int, column: int) -> int:
|
||||||
values = [
|
values = [
|
||||||
[
|
[
|
||||||
self.rows[other_row][other_column]
|
self.rows[other_row][other_column]
|
||||||
|
@ -183,12 +187,12 @@ class Matrix:
|
||||||
]
|
]
|
||||||
return Matrix(values).determinant()
|
return Matrix(values).determinant()
|
||||||
|
|
||||||
def get_cofactor(self, row, column):
|
def get_cofactor(self, row: int, column: int) -> int:
|
||||||
if (row + column) % 2 == 0:
|
if (row + column) % 2 == 0:
|
||||||
return self.get_minor(row, column)
|
return self.get_minor(row, column)
|
||||||
return -1 * self.get_minor(row, column)
|
return -1 * self.get_minor(row, column)
|
||||||
|
|
||||||
def minors(self):
|
def minors(self) -> Matrix:
|
||||||
return Matrix(
|
return Matrix(
|
||||||
[
|
[
|
||||||
[self.get_minor(row, column) for column in range(self.num_columns)]
|
[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(
|
return Matrix(
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
|
@ -209,25 +213,27 @@ class Matrix:
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def adjugate(self):
|
def adjugate(self) -> Matrix:
|
||||||
values = [
|
values = [
|
||||||
[self.cofactors().rows[column][row] for column in range(self.num_columns)]
|
[self.cofactors().rows[column][row] for column in range(self.num_columns)]
|
||||||
for row in range(self.num_rows)
|
for row in range(self.num_rows)
|
||||||
]
|
]
|
||||||
return Matrix(values)
|
return Matrix(values)
|
||||||
|
|
||||||
def inverse(self):
|
def inverse(self) -> Matrix:
|
||||||
determinant = self.determinant()
|
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)
|
return str(self.rows)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
if self.num_rows == 0:
|
if self.num_rows == 0:
|
||||||
return "[]"
|
return "[]"
|
||||||
if self.num_rows == 1:
|
if self.num_rows == 1:
|
||||||
return "[[" + ". ".join(self.rows[0]) + "]]"
|
return "[[" + ". ".join(str(self.rows[0])) + "]]"
|
||||||
return (
|
return (
|
||||||
"["
|
"["
|
||||||
+ "\n ".join(
|
+ "\n ".join(
|
||||||
|
@ -240,7 +246,7 @@ class Matrix:
|
||||||
)
|
)
|
||||||
|
|
||||||
# MATRIX MANIPULATION
|
# 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")
|
type_error = TypeError("Row must be a list containing all ints and/or floats")
|
||||||
if not isinstance(row, list):
|
if not isinstance(row, list):
|
||||||
raise type_error
|
raise type_error
|
||||||
|
@ -256,7 +262,7 @@ class Matrix:
|
||||||
else:
|
else:
|
||||||
self.rows = self.rows[0:position] + [row] + self.rows[position:]
|
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(
|
type_error = TypeError(
|
||||||
"Column must be a list containing all ints and/or floats"
|
"Column must be a list containing all ints and/or floats"
|
||||||
)
|
)
|
||||||
|
@ -278,18 +284,18 @@ class Matrix:
|
||||||
]
|
]
|
||||||
|
|
||||||
# MATRIX OPERATIONS
|
# MATRIX OPERATIONS
|
||||||
def __eq__(self, other):
|
def __eq__(self, other: object) -> bool:
|
||||||
if not isinstance(other, Matrix):
|
if not isinstance(other, Matrix):
|
||||||
raise TypeError("A Matrix can only be compared with another Matrix")
|
raise TypeError("A Matrix can only be compared with another Matrix")
|
||||||
return self.rows == other.rows
|
return self.rows == other.rows
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other: object) -> bool:
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self) -> Matrix:
|
||||||
return self * -1
|
return self * -1
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other: Matrix) -> Matrix:
|
||||||
if self.order != other.order:
|
if self.order != other.order:
|
||||||
raise ValueError("Addition requires matrices of the same order")
|
raise ValueError("Addition requires matrices of the same order")
|
||||||
return Matrix(
|
return Matrix(
|
||||||
|
@ -299,7 +305,7 @@ class Matrix:
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other: Matrix) -> Matrix:
|
||||||
if self.order != other.order:
|
if self.order != other.order:
|
||||||
raise ValueError("Subtraction requires matrices of the same order")
|
raise ValueError("Subtraction requires matrices of the same order")
|
||||||
return Matrix(
|
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)):
|
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):
|
elif isinstance(other, Matrix):
|
||||||
if self.num_columns != other.num_rows:
|
if self.num_columns != other.num_rows:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -329,7 +337,7 @@ class Matrix:
|
||||||
"A Matrix can only be multiplied by an int, float, or another 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):
|
if not isinstance(other, int):
|
||||||
raise TypeError("A Matrix can only be raised to the power of an int")
|
raise TypeError("A Matrix can only be raised to the power of an int")
|
||||||
if not self.is_square:
|
if not self.is_square:
|
||||||
|
@ -348,7 +356,7 @@ class Matrix:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@classmethod
|
@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)))
|
return sum(row[i] * column[i] for i in range(len(row)))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@ Functions for 2D matrix operations
|
||||||
|
|
||||||
from __future__ import annotations
|
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]])
|
>>> add([[1,2],[3,4]],[[2,3],[4,5]])
|
||||||
[[3, 5], [7, 9]]
|
[[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")
|
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]])
|
>>> subtract([[1,2],[3,4]],[[2,3],[4,5]])
|
||||||
[[-1, -1], [-1, -1]]
|
[[-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")
|
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)
|
>>> scalar_multiply([[1,2],[3,4]],5)
|
||||||
[[5, 10], [15, 20]]
|
[[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]
|
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]])
|
>>> multiply([[1,2],[3,4]],[[5,5],[7,5]])
|
||||||
[[19, 15], [43, 35]]
|
[[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
|
:param n: dimension for nxn matrix
|
||||||
:type n: int
|
: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)]
|
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
|
>>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS
|
||||||
<map object at ...
|
<map object at ...
|
||||||
|
@ -108,7 +112,7 @@ def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[l
|
||||||
raise TypeError("Expected a matrix, got int/list instead")
|
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)
|
>>> minor([[1, 2], [3, 4]], 1, 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]
|
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]])
|
>>> determinant([[1, 2], [3, 4]])
|
||||||
-2
|
-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]])
|
>>> inverse([[1, 2], [3, 4]])
|
||||||
[[-2.0, 1.0], [1.5, -0.5]]
|
[[-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)
|
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)
|
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])
|
return len(matrix), len(matrix[0])
|
||||||
|
|
||||||
|
|
||||||
def _verify_matrix_sizes(
|
def _verify_matrix_sizes(
|
||||||
matrix_a: list[list], matrix_b: list[list]
|
matrix_a: list[list[int]], matrix_b: list[list[int]]
|
||||||
) -> tuple[tuple, tuple]:
|
) -> tuple[tuple[int, int], tuple[int, int]]:
|
||||||
shape = _shape(matrix_a) + _shape(matrix_b)
|
shape = _shape(matrix_a) + _shape(matrix_b)
|
||||||
if shape[0] != shape[3] or shape[1] != shape[2]:
|
if shape[0] != shape[3] or shape[1] != shape[2]:
|
||||||
raise ValueError(
|
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]})"
|
f"({shape[0], shape[1]}), ({shape[2], shape[3]})"
|
||||||
)
|
)
|
||||||
return (shape[0], shape[2]), (shape[1], shape[3])
|
return (shape[0], shape[2]), (shape[1], shape[3])
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
matrix_a = [[12, 10], [3, 9]]
|
matrix_a = [[12, 10], [3, 9]]
|
||||||
matrix_b = [[3, 4], [7, 4]]
|
matrix_b = [[3, 4], [7, 4]]
|
||||||
matrix_c = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]]
|
matrix_c = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]]
|
||||||
|
|
|
@ -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 = []
|
matrix_c = []
|
||||||
n = len(matrix_a)
|
n = len(matrix_a)
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
|
@ -30,11 +30,11 @@ def multiply(matrix_a, matrix_b):
|
||||||
return matrix_c
|
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)]
|
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)
|
>>> nth_fibonacci_matrix(100)
|
||||||
354224848179261915075
|
354224848179261915075
|
||||||
|
@ -54,7 +54,7 @@ def nth_fibonacci_matrix(n):
|
||||||
return res_matrix[0][0]
|
return res_matrix[0][0]
|
||||||
|
|
||||||
|
|
||||||
def nth_fibonacci_bruteforce(n):
|
def nth_fibonacci_bruteforce(n: int) -> int:
|
||||||
"""
|
"""
|
||||||
>>> nth_fibonacci_bruteforce(100)
|
>>> nth_fibonacci_bruteforce(100)
|
||||||
354224848179261915075
|
354224848179261915075
|
||||||
|
@ -70,7 +70,7 @@ def nth_fibonacci_bruteforce(n):
|
||||||
return fib1
|
return fib1
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
for ordinal in "0th 1st 2nd 3rd 10th 100th 1000th".split():
|
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
|
n = int("".join(c for c in ordinal if c in "0123456789")) # 1000th --> 1000
|
||||||
print(
|
print(
|
||||||
|
|
|
@ -8,7 +8,7 @@ https://stackoverflow.com/questions/42519/how-do-you-rotate-a-two-dimensional-ar
|
||||||
from __future__ import annotations
|
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()
|
>>> make_matrix()
|
||||||
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
|
[[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)]
|
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())
|
>>> rotate_90(make_matrix())
|
||||||
[[4, 8, 12, 16], [3, 7, 11, 15], [2, 6, 10, 14], [1, 5, 9, 13]]
|
[[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))
|
# 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())
|
>>> rotate_180(make_matrix())
|
||||||
[[16, 15, 14, 13], [12, 11, 10, 9], [8, 7, 6, 5], [4, 3, 2, 1]]
|
[[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))
|
# 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())
|
>>> rotate_270(make_matrix())
|
||||||
[[13, 9, 5, 1], [14, 10, 6, 2], [15, 11, 7, 3], [16, 12, 8, 4]]
|
[[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))
|
# 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)]
|
matrix[:] = [list(x) for x in zip(*matrix)]
|
||||||
return matrix
|
return matrix
|
||||||
|
|
||||||
|
|
||||||
def reverse_row(matrix: list[list]) -> list[list]:
|
def reverse_row(matrix: list[list[int]]) -> list[list[int]]:
|
||||||
matrix[:] = matrix[::-1]
|
matrix[:] = matrix[::-1]
|
||||||
return matrix
|
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]
|
matrix[:] = [x[::-1] for x in matrix]
|
||||||
return matrix
|
return matrix
|
||||||
|
|
||||||
|
|
||||||
def print_matrix(matrix: list[list]) -> None:
|
def print_matrix(matrix: list[list[int]]) -> None:
|
||||||
for i in matrix:
|
for i in matrix:
|
||||||
print(*i)
|
print(*i)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
def search_in_a_sorted_matrix(
|
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:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
>>> search_in_a_sorted_matrix(
|
>>> search_in_a_sorted_matrix(
|
||||||
|
@ -30,7 +30,7 @@ def search_in_a_sorted_matrix(
|
||||||
print(f"Key {key} not found")
|
print(f"Key {key} not found")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
mat = [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]]
|
mat = [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]]
|
||||||
x = int(input("Enter the element to be searched:"))
|
x = int(input("Enter the element to be searched:"))
|
||||||
print(mat)
|
print(mat)
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
class Matrix:
|
class Matrix:
|
||||||
"""
|
"""
|
||||||
<class Matrix>
|
<class Matrix>
|
||||||
Matrix structure.
|
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:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__init__>
|
<method Matrix.__init__>
|
||||||
Initialize matrix with given size and default value.
|
Initialize matrix with given size and default value.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 3, 1)
|
>>> a = Matrix(2, 3, 1)
|
||||||
>>> a
|
>>> a
|
||||||
|
@ -20,7 +24,7 @@ class Matrix:
|
||||||
self.row, self.column = row, column
|
self.row, self.column = row, column
|
||||||
self.array = [[default_value for c in range(column)] for r in range(row)]
|
self.array = [[default_value for c in range(column)] for r in range(row)]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__str__>
|
<method Matrix.__str__>
|
||||||
Return string representation of this matrix.
|
Return string representation of this matrix.
|
||||||
|
@ -37,7 +41,7 @@ class Matrix:
|
||||||
string_format_identifier = "%%%ds" % (max_element_length,)
|
string_format_identifier = "%%%ds" % (max_element_length,)
|
||||||
|
|
||||||
# Make string and return
|
# Make string and return
|
||||||
def single_line(row_vector):
|
def single_line(row_vector: list[float]) -> str:
|
||||||
nonlocal string_format_identifier
|
nonlocal string_format_identifier
|
||||||
line = "["
|
line = "["
|
||||||
line += ", ".join(string_format_identifier % (obj,) for obj in row_vector)
|
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)
|
s += "\n".join(single_line(row_vector) for row_vector in self.array)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
def validateIndices(self, loc: tuple):
|
def validateIndices(self, loc: tuple[int, int]) -> bool:
|
||||||
"""
|
"""
|
||||||
<method Matrix.validateIndices>
|
<method Matrix.validateIndices>
|
||||||
Check if given indices are valid to pick element from matrix.
|
Check if given indices are valid to pick element from matrix.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 6, 0)
|
>>> a = Matrix(2, 6, 0)
|
||||||
>>> a.validateIndices((2, 7))
|
>>> a.validateIndices((2, 7))
|
||||||
|
@ -69,11 +72,10 @@ class Matrix:
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __getitem__(self, loc: tuple):
|
def __getitem__(self, loc: tuple[int, int]) -> Any:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__getitem__>
|
<method Matrix.__getitem__>
|
||||||
Return array[row][column] where loc = (row, column).
|
Return array[row][column] where loc = (row, column).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(3, 2, 7)
|
>>> a = Matrix(3, 2, 7)
|
||||||
>>> a[1, 0]
|
>>> a[1, 0]
|
||||||
|
@ -82,11 +84,10 @@ class Matrix:
|
||||||
assert self.validateIndices(loc)
|
assert self.validateIndices(loc)
|
||||||
return self.array[loc[0]][loc[1]]
|
return self.array[loc[0]][loc[1]]
|
||||||
|
|
||||||
def __setitem__(self, loc: tuple, value: float):
|
def __setitem__(self, loc: tuple[int, int], value: float) -> None:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__setitem__>
|
<method Matrix.__setitem__>
|
||||||
Set array[row][column] = value where loc = (row, column).
|
Set array[row][column] = value where loc = (row, column).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 3, 1)
|
>>> a = Matrix(2, 3, 1)
|
||||||
>>> a[1, 2] = 51
|
>>> a[1, 2] = 51
|
||||||
|
@ -98,11 +99,10 @@ class Matrix:
|
||||||
assert self.validateIndices(loc)
|
assert self.validateIndices(loc)
|
||||||
self.array[loc[0]][loc[1]] = value
|
self.array[loc[0]][loc[1]] = value
|
||||||
|
|
||||||
def __add__(self, another):
|
def __add__(self, another: Matrix) -> Matrix:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__add__>
|
<method Matrix.__add__>
|
||||||
Return self + another.
|
Return self + another.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 1, -4)
|
>>> a = Matrix(2, 1, -4)
|
||||||
>>> b = Matrix(2, 1, 3)
|
>>> b = Matrix(2, 1, 3)
|
||||||
|
@ -123,11 +123,10 @@ class Matrix:
|
||||||
result[r, c] = self[r, c] + another[r, c]
|
result[r, c] = self[r, c] + another[r, c]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self) -> Matrix:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__neg__>
|
<method Matrix.__neg__>
|
||||||
Return -self.
|
Return -self.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 2, 3)
|
>>> a = Matrix(2, 2, 3)
|
||||||
>>> a[0, 1] = a[1, 0] = -2
|
>>> a[0, 1] = a[1, 0] = -2
|
||||||
|
@ -143,14 +142,13 @@ class Matrix:
|
||||||
result[r, c] = -self[r, c]
|
result[r, c] = -self[r, c]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __sub__(self, another):
|
def __sub__(self, another: Matrix) -> Matrix:
|
||||||
return self + (-another)
|
return self + (-another)
|
||||||
|
|
||||||
def __mul__(self, another):
|
def __mul__(self, another: int | float | Matrix) -> Matrix:
|
||||||
"""
|
"""
|
||||||
<method Matrix.__mul__>
|
<method Matrix.__mul__>
|
||||||
Return self * another.
|
Return self * another.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 3, 1)
|
>>> a = Matrix(2, 3, 1)
|
||||||
>>> a[0,2] = a[1,2] = 3
|
>>> a[0,2] = a[1,2] = 3
|
||||||
|
@ -177,11 +175,10 @@ class Matrix:
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"Unsupported type given for another ({type(another)})")
|
raise TypeError(f"Unsupported type given for another ({type(another)})")
|
||||||
|
|
||||||
def transpose(self):
|
def transpose(self) -> Matrix:
|
||||||
"""
|
"""
|
||||||
<method Matrix.transpose>
|
<method Matrix.transpose>
|
||||||
Return self^T.
|
Return self^T.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> a = Matrix(2, 3)
|
>>> a = Matrix(2, 3)
|
||||||
>>> for r in range(2):
|
>>> for r in range(2):
|
||||||
|
@ -201,7 +198,7 @@ class Matrix:
|
||||||
result[c, r] = self[r, c]
|
result[c, r] = self[r, c]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def ShermanMorrison(self, u, v):
|
def ShermanMorrison(self, u: Matrix, v: Matrix) -> Any:
|
||||||
"""
|
"""
|
||||||
<method Matrix.ShermanMorrison>
|
<method Matrix.ShermanMorrison>
|
||||||
Apply Sherman-Morrison formula in O(n^2).
|
Apply Sherman-Morrison formula in O(n^2).
|
||||||
|
@ -211,7 +208,6 @@ class Matrix:
|
||||||
impossible to calculate.
|
impossible to calculate.
|
||||||
Warning: This method doesn't check if self is invertible.
|
Warning: This method doesn't check if self is invertible.
|
||||||
Make sure self is invertible before execute this method.
|
Make sure self is invertible before execute this method.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> ainv = Matrix(3, 3, 0)
|
>>> ainv = Matrix(3, 3, 0)
|
||||||
>>> for i in range(3): ainv[i,i] = 1
|
>>> for i in range(3): ainv[i,i] = 1
|
||||||
|
@ -243,7 +239,7 @@ class Matrix:
|
||||||
# Testing
|
# Testing
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
def test1():
|
def test1() -> None:
|
||||||
# a^(-1)
|
# a^(-1)
|
||||||
ainv = Matrix(3, 3, 0)
|
ainv = Matrix(3, 3, 0)
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
|
@ -256,11 +252,11 @@ if __name__ == "__main__":
|
||||||
v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5
|
v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5
|
||||||
print(f"u is {u}")
|
print(f"u is {u}")
|
||||||
print(f"v is {v}")
|
print(f"v is {v}")
|
||||||
print(f"uv^T is {u * v.transpose()}")
|
print("uv^T is %s" % (u * v.transpose()))
|
||||||
# Sherman Morrison
|
# Sherman Morrison
|
||||||
print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}")
|
print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}")
|
||||||
|
|
||||||
def test2():
|
def test2() -> None:
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
"""
|
"""
|
||||||
This program print the matrix in spiral form.
|
This program print the matrix in spiral form.
|
||||||
This problem has been solved through recursive way.
|
This problem has been solved through recursive way.
|
||||||
|
|
||||||
Matrix must satisfy below conditions
|
Matrix must satisfy below conditions
|
||||||
i) matrix should be only one or two dimensional
|
i) matrix should be only one or two dimensional
|
||||||
ii) number of column of all rows should be equal
|
ii) number of column of all rows should be equal
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections.abc import Iterable
|
|
||||||
|
|
||||||
|
def check_matrix(matrix: list[list[int]]) -> bool:
|
||||||
def check_matrix(matrix):
|
|
||||||
# must be
|
# must be
|
||||||
if matrix and isinstance(matrix, Iterable):
|
matrix = list(list(row) for row in matrix)
|
||||||
if isinstance(matrix[0], Iterable):
|
if matrix and isinstance(matrix, list):
|
||||||
|
if isinstance(matrix[0], list):
|
||||||
prev_len = 0
|
prev_len = 0
|
||||||
for row in matrix:
|
for row in matrix:
|
||||||
if prev_len == 0:
|
if prev_len == 0:
|
||||||
|
@ -29,32 +27,48 @@ def check_matrix(matrix):
|
||||||
return result
|
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:
|
if check_matrix(a) and len(a) > 0:
|
||||||
matRow = len(a)
|
a = list(list(row) for row in a)
|
||||||
if isinstance(a[0], Iterable):
|
mat_row = len(a)
|
||||||
matCol = len(a[0])
|
if isinstance(a[0], list):
|
||||||
|
mat_col = len(a[0])
|
||||||
else:
|
else:
|
||||||
for dat in a:
|
for dat in a:
|
||||||
print(dat),
|
print(dat)
|
||||||
return
|
return
|
||||||
|
|
||||||
# horizotal printing increasing
|
# horizotal printing increasing
|
||||||
for i in range(0, matCol):
|
for i in range(0, mat_col):
|
||||||
print(a[0][i]),
|
print(a[0][i])
|
||||||
# vertical printing down
|
# vertical printing down
|
||||||
for i in range(1, matRow):
|
for i in range(1, mat_row):
|
||||||
print(a[i][matCol - 1]),
|
print(a[i][mat_col - 1])
|
||||||
# horizotal printing decreasing
|
# horizotal printing decreasing
|
||||||
if matRow > 1:
|
if mat_row > 1:
|
||||||
for i in range(matCol - 2, -1, -1):
|
for i in range(mat_col - 2, -1, -1):
|
||||||
print(a[matRow - 1][i]),
|
print(a[mat_row - 1][i])
|
||||||
# vertical printing up
|
# vertical printing up
|
||||||
for i in range(matRow - 2, 0, -1):
|
for i in range(mat_row - 2, 0, -1):
|
||||||
print(a[i][0]),
|
print(a[i][0])
|
||||||
remainMat = [row[1 : matCol - 1] for row in a[1 : matRow - 1]]
|
remain_mat = [row[1 : mat_col - 1] for row in a[1 : mat_row - 1]]
|
||||||
if len(remainMat) > 0:
|
if len(remain_mat) > 0:
|
||||||
spiralPrint(remainMat)
|
spiral_print_clockwise(remain_mat)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -64,5 +78,5 @@ def spiralPrint(a):
|
||||||
|
|
||||||
# driver code
|
# driver code
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
a = ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12])
|
a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
|
||||||
spiralPrint(a)
|
spiral_print_clockwise(a)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user