Untitled

mail@pastecode.io avatar
unknown
python
2 years ago
4.1 kB
3
Indexable
Never
import sys
import os


# Класс Matrix

class Matrix: 
    def __init__(self, matrix):
        # Инициализация свойств матрицы
        self.m = len(matrix)
        self.n = len(matrix[0])
        self.matrix = matrix

    # Вывод матрицы
    def __str__(self):
        nl = '\n' # Обход ограничения f-строк на использование обратных слешей
        return f"{nl.join([' '.join([str(j).rjust(3, ' ') for j in i]) for i in self.matrix])}"

    # Определяем сеттер
    def __setitem__(self, key, value):
        self.matrix[key] = value
    
    # Определяем геттер
    def __getitem__(self, key):
        return self.matrix[key]
    
    def laplace(self, is_print=False):
        if self.n == 1 and self.m == 1:
            return self[0][0]
        
        if self.n == 2 and self.m == 2:
            return self[0][0] * self[1][1] - self[0][1] * self[1][0]

        elem = self.find_zeros()

        if is_print:
            print(f"Разложение определителя по {elem[0] + 1} {'строке' if elem[1] == 'row' else 'столбцу'}")

        dets = []

        if elem[1] == 'row':
            for j in range(self.n):
                if self[elem[0]][j] == 0:
                    continue

                new_matrix = Matrix(self.matrix)
                new_matrix.slice(elem[0], j)

                factor = self[elem[0]][j] * (-1)**(elem[0] + j)
                minor = new_matrix.laplace()
                
                dets.append(factor * minor)

                if is_print:
                    print(f"{self[elem[0]][j]}\n{new_matrix} = {factor} * {minor} = {factor * minor}")
        elif elem[1] == 'column':
            for i in range(self.m):
                if self[i][elem[0]] == 0:
                    continue

                new_matrix = Matrix(matrix = self)
                new_matrix.slice(i, elem[0])

                factor = self[i][elem[0]] * (-1)**(i + elem[0])
                minor = new_matrix.laplace()

                dets.append(factor * minor)

                if is_print:
                    print(f"{self[i][elem[0]]}\n{new_matrix} = {factor} * {minor} = {factor * minor}")
        
        determinant = sum(dets)

        if is_print:
            print(f"Определитель матрицы по рекурсивной формуле: {' + '.join(list(map(str, dets)))} = ", end='')
        
        return determinant

    def find_zeros(self):
        # Ищем строку/столбец с максимальным количеством нулей
        rows_zeros = [sum([1 for i in j if i == 0]) for j in self.matrix]
        columns_zeros = [sum([1 for i in range(self.n) if self.matrix[i][j] == 0]) for j in range(self.m)]
        mx = max(max(rows_zeros), max(columns_zeros))
        for i in range(self.m):
            if rows_zeros[i] == mx:
                return (i, 'row')
        for j in range(self.n):
            if columns_zeros[j] == mx:
                return (j, 'column')

    def slice(self, i, j):
        # Разрезаем матрицу
        self.matrix = [column[:j] + column[j+1:] for column in self.matrix[:i] + self.matrix[i+1:]]
        self.n -= 1
        self.m -= 1


# Функция для считывания данных
def read_file():
    if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
        with open(sys.argv[1]) as f:
            return f.read()
    else:
        while True:
            print('Передайте название файла аргументом в командную строку: ', end='')
            file_name = input()
            if os.path.exists(file_name):
                with open(file_name) as f:
                    try:
                        return [[int(num) for num in st.strip().split(' ')] for st in f.readlines()[1::]]
                    except:
                        print("Содержимое файла невалидно")


matrix = Matrix(read_file())
print(matrix)
print(matrix.laplace(True))