Skip to content

Commit 46842e8

Browse files
Add missing type hints in matrix directory (TheAlgorithms#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>
1 parent a84fb58 commit 46842e8

8 files changed

+142
-119
lines changed

matrix/count_islands_in_matrix.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@
44

55

66
class matrix: # Public class to implement a graph
7-
def __init__(self, row: int, col: int, graph: list):
7+
def __init__(self, row: int, col: int, graph: list[list[bool]]) -> None:
88
self.ROW = row
99
self.COL = col
1010
self.graph = graph
1111

12-
def is_safe(self, i, j, visited) -> bool:
12+
def is_safe(self, i: int, j: int, visited: list[list[bool]]) -> bool:
1313
return (
1414
0 <= i < self.ROW
1515
and 0 <= j < self.COL
1616
and not visited[i][j]
1717
and self.graph[i][j]
1818
)
1919

20-
def diffs(self, i, j, visited): # Checking all 8 elements surrounding nth element
20+
def diffs(self, i: int, j: int, visited: list[list[bool]]) -> None:
21+
# Checking all 8 elements surrounding nth element
2122
rowNbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order
2223
colNbr = [-1, 0, 1, -1, 1, -1, 0, 1]
2324
visited[i][j] = True # Make those cells visited

matrix/matrix_class.py

+44-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# An OOP approach to representing and manipulating matrices
22

3+
from __future__ import annotations
4+
35

46
class Matrix:
57
"""
@@ -54,7 +56,9 @@ class Matrix:
5456
[6. -12. 6.]
5557
[-3. 6. -3.]]
5658
>>> print(matrix.inverse())
57-
None
59+
Traceback (most recent call last):
60+
...
61+
TypeError: Only matrices with a non-zero determinant have an inverse
5862
5963
Determinant is an int, float, or Nonetype
6064
>>> matrix.determinant()
@@ -101,10 +105,9 @@ class Matrix:
101105
[198. 243. 288. 304.]
102106
[306. 378. 450. 472.]
103107
[414. 513. 612. 640.]]
104-
105108
"""
106109

107-
def __init__(self, rows):
110+
def __init__(self, rows: list[list[int]]):
108111
error = TypeError(
109112
"Matrices must be formed from a list of zero or more lists containing at "
110113
"least one and the same number of values, each of which must be of type "
@@ -125,53 +128,54 @@ def __init__(self, rows):
125128
self.rows = []
126129

127130
# MATRIX INFORMATION
128-
def columns(self):
131+
def columns(self) -> list[list[int]]:
129132
return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]
130133

131134
@property
132-
def num_rows(self):
135+
def num_rows(self) -> int:
133136
return len(self.rows)
134137

135138
@property
136-
def num_columns(self):
139+
def num_columns(self) -> int:
137140
return len(self.rows[0])
138141

139142
@property
140-
def order(self):
143+
def order(self) -> tuple[int, int]:
141144
return (self.num_rows, self.num_columns)
142145

143146
@property
144-
def is_square(self):
147+
def is_square(self) -> bool:
145148
return self.order[0] == self.order[1]
146149

147-
def identity(self):
150+
def identity(self) -> Matrix:
148151
values = [
149152
[0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
150153
for row_num in range(self.num_rows)
151154
]
152155
return Matrix(values)
153156

154-
def determinant(self):
157+
def determinant(self) -> int:
155158
if not self.is_square:
156-
return None
159+
return 0
157160
if self.order == (0, 0):
158161
return 1
159162
if self.order == (1, 1):
160-
return self.rows[0][0]
163+
return int(self.rows[0][0])
161164
if self.order == (2, 2):
162-
return (self.rows[0][0] * self.rows[1][1]) - (
163-
self.rows[0][1] * self.rows[1][0]
165+
return int(
166+
(self.rows[0][0] * self.rows[1][1])
167+
- (self.rows[0][1] * self.rows[1][0])
164168
)
165169
else:
166170
return sum(
167171
self.rows[0][column] * self.cofactors().rows[0][column]
168172
for column in range(self.num_columns)
169173
)
170174

171-
def is_invertable(self):
175+
def is_invertable(self) -> bool:
172176
return bool(self.determinant())
173177

174-
def get_minor(self, row, column):
178+
def get_minor(self, row: int, column: int) -> int:
175179
values = [
176180
[
177181
self.rows[other_row][other_column]
@@ -183,20 +187,20 @@ def get_minor(self, row, column):
183187
]
184188
return Matrix(values).determinant()
185189

186-
def get_cofactor(self, row, column):
190+
def get_cofactor(self, row: int, column: int) -> int:
187191
if (row + column) % 2 == 0:
188192
return self.get_minor(row, column)
189193
return -1 * self.get_minor(row, column)
190194

191-
def minors(self):
195+
def minors(self) -> Matrix:
192196
return Matrix(
193197
[
194198
[self.get_minor(row, column) for column in range(self.num_columns)]
195199
for row in range(self.num_rows)
196200
]
197201
)
198202

199-
def cofactors(self):
203+
def cofactors(self) -> Matrix:
200204
return Matrix(
201205
[
202206
[
@@ -209,25 +213,27 @@ def cofactors(self):
209213
]
210214
)
211215

212-
def adjugate(self):
216+
def adjugate(self) -> Matrix:
213217
values = [
214218
[self.cofactors().rows[column][row] for column in range(self.num_columns)]
215219
for row in range(self.num_rows)
216220
]
217221
return Matrix(values)
218222

219-
def inverse(self):
223+
def inverse(self) -> Matrix:
220224
determinant = self.determinant()
221-
return None if not determinant else self.adjugate() * (1 / determinant)
225+
if not determinant:
226+
raise TypeError("Only matrices with a non-zero determinant have an inverse")
227+
return self.adjugate() * (1 / determinant)
222228

223-
def __repr__(self):
229+
def __repr__(self) -> str:
224230
return str(self.rows)
225231

226-
def __str__(self):
232+
def __str__(self) -> str:
227233
if self.num_rows == 0:
228234
return "[]"
229235
if self.num_rows == 1:
230-
return "[[" + ". ".join(self.rows[0]) + "]]"
236+
return "[[" + ". ".join(str(self.rows[0])) + "]]"
231237
return (
232238
"["
233239
+ "\n ".join(
@@ -240,7 +246,7 @@ def __str__(self):
240246
)
241247

242248
# MATRIX MANIPULATION
243-
def add_row(self, row, position=None):
249+
def add_row(self, row: list[int], position: int | None = None) -> None:
244250
type_error = TypeError("Row must be a list containing all ints and/or floats")
245251
if not isinstance(row, list):
246252
raise type_error
@@ -256,7 +262,7 @@ def add_row(self, row, position=None):
256262
else:
257263
self.rows = self.rows[0:position] + [row] + self.rows[position:]
258264

259-
def add_column(self, column, position=None):
265+
def add_column(self, column: list[int], position: int | None = None) -> None:
260266
type_error = TypeError(
261267
"Column must be a list containing all ints and/or floats"
262268
)
@@ -278,18 +284,18 @@ def add_column(self, column, position=None):
278284
]
279285

280286
# MATRIX OPERATIONS
281-
def __eq__(self, other):
287+
def __eq__(self, other: object) -> bool:
282288
if not isinstance(other, Matrix):
283289
raise TypeError("A Matrix can only be compared with another Matrix")
284290
return self.rows == other.rows
285291

286-
def __ne__(self, other):
292+
def __ne__(self, other: object) -> bool:
287293
return not self == other
288294

289-
def __neg__(self):
295+
def __neg__(self) -> Matrix:
290296
return self * -1
291297

292-
def __add__(self, other):
298+
def __add__(self, other: Matrix) -> Matrix:
293299
if self.order != other.order:
294300
raise ValueError("Addition requires matrices of the same order")
295301
return Matrix(
@@ -299,7 +305,7 @@ def __add__(self, other):
299305
]
300306
)
301307

302-
def __sub__(self, other):
308+
def __sub__(self, other: Matrix) -> Matrix:
303309
if self.order != other.order:
304310
raise ValueError("Subtraction requires matrices of the same order")
305311
return Matrix(
@@ -309,9 +315,11 @@ def __sub__(self, other):
309315
]
310316
)
311317

312-
def __mul__(self, other):
318+
def __mul__(self, other: Matrix | int | float) -> Matrix:
313319
if isinstance(other, (int, float)):
314-
return Matrix([[element * other for element in row] for row in self.rows])
320+
return Matrix(
321+
[[int(element * other) for element in row] for row in self.rows]
322+
)
315323
elif isinstance(other, Matrix):
316324
if self.num_columns != other.num_rows:
317325
raise ValueError(
@@ -329,7 +337,7 @@ def __mul__(self, other):
329337
"A Matrix can only be multiplied by an int, float, or another matrix"
330338
)
331339

332-
def __pow__(self, other):
340+
def __pow__(self, other: int) -> Matrix:
333341
if not isinstance(other, int):
334342
raise TypeError("A Matrix can only be raised to the power of an int")
335343
if not self.is_square:
@@ -348,7 +356,7 @@ def __pow__(self, other):
348356
return result
349357

350358
@classmethod
351-
def dot_product(cls, row, column):
359+
def dot_product(cls, row: list[int], column: list[int]) -> int:
352360
return sum(row[i] * column[i] for i in range(len(row)))
353361

354362

matrix/matrix_operation.py

+19-15
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
from __future__ import annotations
66

7+
from typing import Any
78

8-
def add(*matrix_s: list[list]) -> list[list]:
9+
10+
def add(*matrix_s: list[list[int]]) -> list[list[int]]:
911
"""
1012
>>> add([[1,2],[3,4]],[[2,3],[4,5]])
1113
[[3, 5], [7, 9]]
@@ -25,7 +27,7 @@ def add(*matrix_s: list[list]) -> list[list]:
2527
raise TypeError("Expected a matrix, got int/list instead")
2628

2729

28-
def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]:
30+
def subtract(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]:
2931
"""
3032
>>> subtract([[1,2],[3,4]],[[2,3],[4,5]])
3133
[[-1, -1], [-1, -1]]
@@ -45,7 +47,7 @@ def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]:
4547
raise TypeError("Expected a matrix, got int/list instead")
4648

4749

48-
def scalar_multiply(matrix: list[list], n: int | float) -> list[list]:
50+
def scalar_multiply(matrix: list[list[int]], n: int | float) -> list[list[float]]:
4951
"""
5052
>>> scalar_multiply([[1,2],[3,4]],5)
5153
[[5, 10], [15, 20]]
@@ -55,7 +57,7 @@ def scalar_multiply(matrix: list[list], n: int | float) -> list[list]:
5557
return [[x * n for x in row] for row in matrix]
5658

5759

58-
def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]:
60+
def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]:
5961
"""
6062
>>> multiply([[1,2],[3,4]],[[5,5],[7,5]])
6163
[[19, 15], [43, 35]]
@@ -77,7 +79,7 @@ def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]:
7779
]
7880

7981

80-
def identity(n: int) -> list[list]:
82+
def identity(n: int) -> list[list[int]]:
8183
"""
8284
:param n: dimension for nxn matrix
8385
:type n: int
@@ -89,7 +91,9 @@ def identity(n: int) -> list[list]:
8991
return [[int(row == column) for column in range(n)] for row in range(n)]
9092

9193

92-
def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[list]:
94+
def transpose(
95+
matrix: list[list[int]], return_map: bool = True
96+
) -> list[list[int]] | map[list[int]]:
9397
"""
9498
>>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS
9599
<map object at ...
@@ -108,7 +112,7 @@ def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[l
108112
raise TypeError("Expected a matrix, got int/list instead")
109113

110114

111-
def minor(matrix: list[list], row: int, column: int) -> list[list]:
115+
def minor(matrix: list[list[int]], row: int, column: int) -> list[list[int]]:
112116
"""
113117
>>> minor([[1, 2], [3, 4]], 1, 1)
114118
[[1]]
@@ -117,7 +121,7 @@ def minor(matrix: list[list], row: int, column: int) -> list[list]:
117121
return [row[:column] + row[column + 1 :] for row in minor]
118122

119123

120-
def determinant(matrix: list[list]) -> int:
124+
def determinant(matrix: list[list[int]]) -> Any:
121125
"""
122126
>>> determinant([[1, 2], [3, 4]])
123127
-2
@@ -133,7 +137,7 @@ def determinant(matrix: list[list]) -> int:
133137
)
134138

135139

136-
def inverse(matrix: list[list]) -> list[list] | None:
140+
def inverse(matrix: list[list[int]]) -> list[list[float]] | None:
137141
"""
138142
>>> inverse([[1, 2], [3, 4]])
139143
[[-2.0, 1.0], [1.5, -0.5]]
@@ -157,27 +161,27 @@ def inverse(matrix: list[list]) -> list[list] | None:
157161
return scalar_multiply(adjugate, 1 / det)
158162

159163

160-
def _check_not_integer(matrix: list[list]) -> bool:
164+
def _check_not_integer(matrix: list[list[int]]) -> bool:
161165
return not isinstance(matrix, int) and not isinstance(matrix[0], int)
162166

163167

164-
def _shape(matrix: list[list]) -> tuple[int, int]:
168+
def _shape(matrix: list[list[int]]) -> tuple[int, int]:
165169
return len(matrix), len(matrix[0])
166170

167171

168172
def _verify_matrix_sizes(
169-
matrix_a: list[list], matrix_b: list[list]
170-
) -> tuple[tuple, tuple]:
173+
matrix_a: list[list[int]], matrix_b: list[list[int]]
174+
) -> tuple[tuple[int, int], tuple[int, int]]:
171175
shape = _shape(matrix_a) + _shape(matrix_b)
172176
if shape[0] != shape[3] or shape[1] != shape[2]:
173177
raise ValueError(
174-
"operands could not be broadcast together with shape "
178+
f"operands could not be broadcast together with shape "
175179
f"({shape[0], shape[1]}), ({shape[2], shape[3]})"
176180
)
177181
return (shape[0], shape[2]), (shape[1], shape[3])
178182

179183

180-
def main():
184+
def main() -> None:
181185
matrix_a = [[12, 10], [3, 9]]
182186
matrix_b = [[3, 4], [7, 4]]
183187
matrix_c = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]]

0 commit comments

Comments
 (0)