diff --git a/src/Test #2/Matrix/__init__.py b/src/Test #2/Matrix/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/Test #2/Matrix/frozen_matrix.py b/src/Test #2/Matrix/frozen_matrix.py new file mode 100644 index 0000000..9b1b4ef --- /dev/null +++ b/src/Test #2/Matrix/frozen_matrix.py @@ -0,0 +1,23 @@ +from matrix import Matrix + + +class FrozenMatrix(Matrix): + def __init__(self, size: tuple[int, int], values: list[list[float | int]]) -> None: + frozen_values = tuple(tuple(row) for row in values) + super().__init__(size, [list(row) for row in frozen_values]) + self.hash = None + + def __hash__(self) -> int: + if self.hash is None: + flattered_matrix = tuple( + self.values[row][column] + for row in range(self.size[0]) + for column in range(self.size[1]) + ) + self.hash = hash((self.size, flattered_matrix)) + return self.hash + + def __eq__(self, other): + if not isinstance(other, (FrozenMatrix, Matrix)): + return False + return self.size == other.size and self.values == other.values diff --git a/src/Test #2/Matrix/matrix.py b/src/Test #2/Matrix/matrix.py new file mode 100644 index 0000000..eee7e84 --- /dev/null +++ b/src/Test #2/Matrix/matrix.py @@ -0,0 +1,108 @@ +from typing import Self + + +class Matrix: + def __init__(self, size: tuple[int, int], values: list[list[float | int]]) -> None: + if len(values) != size[0]: + raise ValueError + self.matrix = [] + for row in values: + if len(row) != size[1]: + raise ValueError + + self.values = values + self.size = size + + def determinant(self) -> float | int: + if self.size[0] != self.size[1]: + raise ValueError + + row_number = self.size[0] + + if row_number == 1: + return float(self.values[0][0]) + + if row_number == 2: + return float( + self.values[0][0] * self.values[1][1] + - self.values[0][1] * self.values[1][0] + ) + + matrix = [row[:] for row in self.values] + + det = 0.0 + + for column_index in range(row_number): + minor_values = [] + for i in range(1, row_number): + row = [] + for j in range(row_number): + if j != column_index: + row.append(matrix[i][j]) + minor_values.append(row) + + minor = Matrix((row_number - 1, row_number - 1), minor_values) + + minor_det = minor.determinant() + + det += ((-1) ** column_index) * matrix[0][column_index] * minor_det + + return det + + def __add__(self, other_matrix: Self) -> Self: + if self.size != other_matrix.size: + raise ValueError + + result = [] + for row_index in range(self.size[0]): + row = [] + for column_index in range(self.size[1]): + row.append( + self.values[row_index][column_index] + + other_matrix.values[row_index][column_index] + ) + result.append(row) + + return self.__class__(self.size, result) + + def __mul__(self, multiplier: float | int | Self) -> Self: + if isinstance(multiplier, (float, int)): + result = [] + for row_index in range(self.size[0]): + row = [] + for column_index in range(self.size[1]): + row.append(self.values[row_index][column_index] * multiplier) + result.append(row) + + return self.__class__(self.size, result) + elif isinstance(multiplier, Matrix): + if self.size[1] != multiplier.size[0]: + raise ValueError + + result = [] + for i in range(self.size[0]): + row = [] + for j in range(multiplier.size[1]): + element_sum = 0 + for k in range(self.size[1]): + element_sum += self.values[i][k] * multiplier.values[k][j] + row.append(element_sum) + result.append(row) + + return self.__class__((self.size[0], multiplier.size[1]), result) + else: + return NotImplemented + + def __rmul__(self, multiplier: float | int) -> Self: + if isinstance(multiplier, (float, int)): + return self.__mul__(multiplier) + + return NotImplemented + + def __sub__(self, other_matrix: Self) -> Self: + return self + (-1 * other_matrix) + + def __iter__(self): + for row in self.values: + for element in row: + yield element