# Autor - https://pt.stackoverflow.com/users/132
class Matriz:
    def __init__(self, largura, altura, valores):
        if len(valores) != altura:
            raise IndexError("O conjunto de valores não tem o tamanho correto.")
        for linha in valores:
            if len(linha) != largura:
                raise IndexError("O conjunto de valores não tem o tamanho correto.")
        self.__valores = valores

    @property
    def largura(self):
        return len(self.__valores[0])

    @property
    def altura(self):
        return len(self.__valores)

    def valor(self, num_linha, num_coluna):
        if num_linha < 0 or num_linha >= self.altura or num_coluna < 0 or num_coluna >= self.largura:
            raise IndexError(f"Não há posição a_{num_linha}_{num_coluna}.")
        return self.__valores[num_linha][num_coluna]

    def definir(self, num_linha, num_coluna, valor):
        if num_linha < 0 or num_linha >= self.altura or num_coluna < 0 or num_coluna >= self.largura:
            raise IndexError(f"Não há posição a_{num_linha}_{num_coluna}.")
        self.__valores[num_linha][num_coluna] = valor

    def multiplicar_linha(self, num_linha, valor):
        if num_linha < 0 or num_linha >= self.altura:
            raise IndexError(f"Não há linha {num_linha}.")
        for coluna in range(0, self.largura):
            self.__valores[num_linha][coluna] *= valor

    def somar_linha(self, num_linha, valores, multiplicador):
        if num_linha < 0 or num_linha >= self.altura:
            raise IndexError(f"Não há linha {num_linha}.")
        if len(valores) != self.largura:
            raise IndexError("O conjunto de valores não tem o tamanho correto.")
        for coluna in range(0, self.largura):
            self.__valores[num_linha][coluna] += valores[coluna] * multiplicador

    def linha(self, num_linha):
        if num_linha < 0 or num_linha >= self.altura:
            raise IndexError(f"Não há linha {num_linha}.")
        return self.__valores[num_linha]

    @staticmethod
    def triangular_inferior(lista_1, lista_2):
        t = len(lista_2)
        if t * (t + 1) / 2 != len(lista_1):
            raise IndexError("A segunda lista não tem a quantidade correta de termos.")
        matriz = []
        n = 0
        for i in range(0, t):
            linha = []
            for j in range(0, i + 1):
                linha.append(lista_1[n])
                n += 1
            for j in range(i + 1, t):
                linha.append(0)
            matriz.append(linha)
            linha.append(lista_2[i])
        return Matriz(t + 1, t, matriz)

    def eliminacao_gauss(self):
        for i in range(0, self.altura):
            if self.__valores[i][i] == 0:
                raise IndexError("Zero na coluna principal.")
        for i in range(0, self.altura):
            self.multiplicar_linha(i, 1 / self.__valores[i][i])
            for j in range(i + 1, self.altura):
                self.somar_linha(j, self.__valores[i], -self.__valores[j][i])
        ret = []
        for i in range(0, self.altura):
            ret.append(self.__valores[i][-1])
        return ret

    def __str__(self):
        t = ""
        for i in range(0, self.altura):
            for j in range(0, self.largura):
                v = self.__valores[i][j]
                if j == self.largura - 1:
                    t += f" = {v: >6.2f}"
                else:
                    if j != 0: t += " "
                    if v == 0:
                        t += " " * (12 + len(str(j + 1)))
                    else:
                        s = "+" if v > 0 else "-"
                        t += f"{s} {abs(v): >6.2f} * x{j + 1}"
            t += "\n"
        return t

def mostra_vetor(vetor):
    aux = ""
    for i in range(0, len(vetor)):
        aux += f"{vetor[i]} * x{i + 1}\n"
    return aux

m = Matriz.triangular_inferior([-13, 13, 3, -5, -1, -1, 3, 0, 1, 1], [-13, 13, -7, 4])
print(m)
resultado = m.eliminacao_gauss()
print(resultado)
print(mostra_vetor(resultado))