Python 3 matrix calculator - python

I have an issue with this code, It works wrong on option 7 at least is the main problem, It should do the matrix modify and save new value like 2A(A s 2) should be saved on A and maybe because it doesn't update to new value it gives wrong output, please help.
CODE:
class Matrix:
def __init__(self, name, m, n, values):
self.name = name
self.m = m
self.n = n
self.values = values
def __str__(self):
rows = [self.values[i:i+self.n] for i in range(0, len(self.values), self.n)]
return f'{self.name} = \n' + '\n'.join([' '.join(map(str, row)) for row in rows])
class MatrixMultiplier:
def __init__(self):
self.matrices = []
def create_matrix(self, name):
m = int(input(f'Introduceți numărul de rânduri pentru matricea {name}: '))
n = int(input(f'Introduceți numărul de coloane pentru matricea {name}: '))
values = []
for i in range(m):
for j in range(n):
value = int(input(f'Introduceți valoarea pentru poziție ({i}, {j}) în matricea {name}: '))
values.append(value)
matrix = Matrix(name, m, n, values)
self.matrices.append(matrix)
def add_matrices(self, name1, name2):
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] + matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}+{name2}', matrix1.m, matrix1.n, result)
def multiply_matrices(self, name1, name2):
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.n != matrix2.m:
raise ValueError('Numărul de coloane din prima matrice trebuie să se potrivească cu numărul de rânduri din a doua matrice')
result = []
for i in range(matrix1.m):
for j in range(matrix2.n):
val = 0
for k in range(matrix1.n):
val += matrix1.values[i * matrix1.n + k] * matrix2.values[k * matrix2.n + j]
result.append(val)
return Matrix(f'{name1}{name2}', matrix1.m, matrix2.n, result)
def scalar_multiply(self, name, scalar):
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = [scalar * val for val in matrix.values]
matrix.values = result
matrix.name = f'{scalar}{name}'
return Matrix(f'{scalar}{name}', matrix.m, matrix.n, result)
def flip_matrix(self, name):
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = []
for j in range(matrix.n):
for i in range(matrix.m):
result.append(matrix.values[i * matrix.n + j])
matrix.values = result
matrix.m, matrix.n = matrix.n, matrix.m
matrix.name = f'{name}^T'
return matrix
def subtract_matrices(self, name1, name2):
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] - matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}-{name2}', matrix1.m, matrix1.n, result)
def custom_input(self, ops):
ops = ops.split()
name = ops[0]
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
for i in range(1, len(ops), 2):
op = ops[i]
if op == 's':
scalar = int(ops[i + 1])
matrix = self.scalar_multiply(matrix.name, scalar)
self.matrices[self.matrices.index(next(matrix for matrix in self.matrices if matrix.name == matrix.name))] = matrix
elif op == '+':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.add_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
elif op == '-':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.subtract_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
elif op == 't':
matrix = self.flip_matrix(matrix.name)
self.matrices[self.matrices.index(next(matrix for matrix in self.matrices if matrix.name == matrix.name))] = matrix
return matrix
def print_menu():
...
print('7. Intrare personalizată')
print('8. Ieșire')
def main():
matrix_multiplier = MatrixMultiplier()
while True:
print_menu()
choice = input('Introdu alegerea ta: ')
...
elif choice == '7':
update_con = input('Vrei sa salvezi noile valori?: ')
if update_con in ['yes', 'y']:
update_con = 1
operations = input('Introduceți succesiunea operațiilor cu matrice: ')
try:
result = matrix_multiplier.custom_input(operations)
print(result)
except (ValueError, IndexError) as e:
print(e)
else:
print('Alegere nevalidă')
if __name__ == '__main__':
main()
So basically it works fine when I do singular matrix math on it but When I do option 7 (custom input), I get wrong answer.
Here is my WRONG output:
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 1
Introduceți numele matricei: A
Introduceți numărul de rânduri pentru matricea A: 3
Introduceți numărul de coloane pentru matricea A: 3
Introduceți valoarea pentru poziție (0, 0) în matricea A: 1
Introduceți valoarea pentru poziție (0, 1) în matricea A: -1
Introduceți valoarea pentru poziție (0, 2) în matricea A: 0
Introduceți valoarea pentru poziție (1, 0) în matricea A: 0
Introduceți valoarea pentru poziție (1, 1) în matricea A: -2
Introduceți valoarea pentru poziție (1, 2) în matricea A: 1
Introduceți valoarea pentru poziție (2, 0) în matricea A: -2
Introduceți valoarea pentru poziție (2, 1) în matricea A: 3
Introduceți valoarea pentru poziție (2, 2) în matricea A: 1
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 1
Introduceți numele matricei: B
Introduceți numărul de rânduri pentru matricea B: 3
Introduceți numărul de coloane pentru matricea B: 3
Introduceți valoarea pentru poziție (0, 0) în matricea B: 1
Introduceți valoarea pentru poziție (0, 1) în matricea B: 1
Introduceți valoarea pentru poziție (0, 2) în matricea B: -1
Introduceți valoarea pentru poziție (1, 0) în matricea B: 0
Introduceți valoarea pentru poziție (1, 1) în matricea B: 2
Introduceți valoarea pentru poziție (1, 2) în matricea B: 3
Introduceți valoarea pentru poziție (2, 0) în matricea B: 1
Introduceți valoarea pentru poziție (2, 1) în matricea B: 4
Introduceți valoarea pentru poziție (2, 2) în matricea B: 1
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 7
Vrei sa salvezi noile valori?: y
Introduceți succesiunea operațiilor cu matrice: A s 2 - B t
2A-B^T =
1 0 -5
-3 -6 2
1 -1 1
Here is how it should be it RIGHT:
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 1
Introduceți numele matricei: A
Introduceți numărul de rânduri pentru matricea A: 3
Introduceți numărul de coloane pentru matricea A: 3
Introduceți valoarea pentru poziție (0, 0) în matricea A: 1
Introduceți valoarea pentru poziție (0, 1) în matricea A: -1
Introduceți valoarea pentru poziție (0, 2) în matricea A: 0
Introduceți valoarea pentru poziție (1, 0) în matricea A: 0
Introduceți valoarea pentru poziție (1, 1) în matricea A: -2
Introduceți valoarea pentru poziție (1, 2) în matricea A: 1
Introduceți valoarea pentru poziție (2, 0) în matricea A: -2
Introduceți valoarea pentru poziție (2, 1) în matricea A: 3
Introduceți valoarea pentru poziție (2, 2) în matricea A: 1
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 1
Introduceți numele matricei: B
Introduceți numărul de rânduri pentru matricea B: 3
Introduceți numărul de coloane pentru matricea B: 3
Introduceți valoarea pentru poziție (0, 0) în matricea B: 1
Introduceți valoarea pentru poziție (0, 1) în matricea B: 1
Introduceți valoarea pentru poziție (0, 2) în matricea B: -1
Introduceți valoarea pentru poziție (1, 0) în matricea B: 0
Introduceți valoarea pentru poziție (1, 1) în matricea B: 2
Introduceți valoarea pentru poziție (1, 2) în matricea B: 3
Introduceți valoarea pentru poziție (2, 0) în matricea B: 1
Introduceți valoarea pentru poziție (2, 1) în matricea B: 4
Introduceți valoarea pentru poziție (2, 2) în matricea B: 1
1. Creați matrice
2. Înmulțiți matrice
3. Înmulțire scalară
4. Adăugați matrice
5. Scăderea matricilor
6. Flip Matrix
7. Intrare personalizată
8. Ieșire
Introdu alegerea ta: 7
Vrei sa salvezi noile valori?: y
Introduceți succesiunea operațiilor cu matrice: A s 2 - B t
2A-B^T =
1 -2 -1
-1 -6 -2
-3 3 1
can somebody help me?

Here is a way to test your code and find the bug:
First of all you must understand if your problem is in the parsing of user input or in the mathematics of the computations. To do so, write a way to initialize your MatrixMultiplier from code rather than user input, then check the results of your multiplication with the result of any matrix multiplication website that you find online. If you get a wrong result, work on math logic, if you get a right result work on handling user input.
I mean like
def __init__(self, matrices=None):
self.matrices = [] if matrices == None else matrices
so you can generate this from code rather than inputting all numbers manually, then write tests with doctest or unittest to check that the mathematical logic of the operations is right.
Here is your code with this change and an automated test:
import doctest
class Matrix:
def __init__(self, name, m, n, values):
self.name = name
self.m = m
self.n = n
self.values = values
def __str__(self):
rows = [self.values[i:i+self.n] for i in range(0, len(self.values), self.n)]
return f'{self.name} = \n' + '\n'.join([' '.join(map(str, row)) for row in rows])
def __repr__(self):
return f'Matrix({self.name}, {self.m}, {self.n}, {self.values})'
class MatrixMultiplier:
def __init__(self, matrices=None):
self.matrices = [] if matrices is None else matrices
def create_matrix(self, name):
m = int(input(f'Introduceți numărul de rânduri pentru matricea {name}: '))
n = int(input(f'Introduceți numărul de coloane pentru matricea {name}: '))
values = []
for i in range(m):
for j in range(n):
value = int(input(f'Introduceți valoarea pentru poziție ({i}, {j}) în matricea {name}: '))
values.append(value)
matrix = Matrix(name, m, n, values)
self.matrices.append(matrix)
def add_matrices(self, name1, name2):
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] + matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}+{name2}', matrix1.m, matrix1.n, result)
def multiply_matrices(self, name1, name2):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> m2 = Matrix('B', 2, 2, [0, 1, 2, 3])
>>> MatrixMultiplier(matrices=[m1, m2]).multiply_matrices(m1.name, m2.name)
Matrix(AB, 2, 2, [4, 7, 8, 15])
"""
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.n != matrix2.m:
raise ValueError('Numărul de coloane din prima matrice trebuie să se potrivească cu numărul de rânduri din a doua matrice')
result = []
for i in range(matrix1.m):
for j in range(matrix2.n):
val = 0
for k in range(matrix1.n):
val += matrix1.values[i * matrix1.n + k] * matrix2.values[k * matrix2.n + j]
result.append(val)
return Matrix(f'{name1}{name2}', matrix1.m, matrix2.n, result)
def scalar_multiply(self, name, scalar):
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = [scalar * val for val in matrix.values]
matrix.values = result
matrix.name = f'{scalar}{name}'
return Matrix(f'{scalar}{name}', matrix.m, matrix.n, result)
def flip_matrix(self, name):
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = []
for j in range(matrix.n):
for i in range(matrix.m):
result.append(matrix.values[i * matrix.n + j])
matrix.values = result
matrix.m, matrix.n = matrix.n, matrix.m
matrix.name = f'{name}^T'
return matrix
def subtract_matrices(self, name1, name2):
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] - matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}-{name2}', matrix1.m, matrix1.n, result)
def custom_input(self, ops):
ops = ops.split()
name = ops[0]
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
for i in range(1, len(ops), 2):
op = ops[i]
if op == 's':
scalar = int(ops[i + 1])
matrix = self.scalar_multiply(matrix.name, scalar)
self.matrices[self.matrices.index(next(matrix for matrix in self.matrices if matrix.name == matrix.name))] = matrix
elif op == '+':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.add_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
elif op == '-':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.subtract_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
elif op == 't':
matrix = self.flip_matrix(matrix.name)
self.matrices[self.matrices.index(next(matrix for matrix in self.matrices if matrix.name == matrix.name))] = matrix
return matrix
if __name__ == "__main__":
doctest.testmod()
This test passes, where I got the correct result from a matrix multiplication website online (see result from the website in the image). (Assuming that the first matrix is [[1,2]],[3,4]]). Now you can focus on the input handling method and fix the bug there.
So the error is most likely in the input handling.
Here is the fully fixed code, the trick was handling the transpose before because it has higher precedence and being careful about the name changes.
import doctest
class Matrix:
def __init__(self, name, m, n, values):
self.name = name
self.m = m
self.n = n
self.values = values
def __str__(self):
rows = [self.values[i:i+self.n] for i in range(0, len(self.values), self.n)]
return f'{self.name} = \n' + '\n'.join([' '.join(map(str, row)) for row in rows])
def __repr__(self):
return f'Matrix({self.name}, {self.m}, {self.n}, {self.values})'
class MatrixMultiplier:
def __init__(self, matrices=None):
self.matrices = [] if matrices is None else matrices
def create_matrix(self, name):
m = int(input(f'Introduceți numărul de rânduri pentru matricea {name}: '))
n = int(input(f'Introduceți numărul de coloane pentru matricea {name}: '))
values = []
for i in range(m):
for j in range(n):
value = int(input(f'Introduceți valoarea pentru poziție ({i}, {j}) în matricea {name}: '))
values.append(value)
matrix = Matrix(name, m, n, values)
self.matrices.append(matrix)
def add_matrices(self, name1, name2):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> m2 = Matrix('B', 2, 2, [0, 1, 2, 3])
>>> MatrixMultiplier([m1, m2]).add_matrices('A', 'B')
Matrix(A+B, 2, 2, [1, 3, 5, 7])
"""
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] + matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}+{name2}', matrix1.m, matrix1.n, result)
def multiply_matrices(self, name1, name2):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> m2 = Matrix('B', 2, 2, [0, 1, 2, 3])
>>> MatrixMultiplier(matrices=[m1, m2]).multiply_matrices(m1.name, m2.name)
Matrix(AB, 2, 2, [4, 7, 8, 15])
"""
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.n != matrix2.m:
raise ValueError('Numărul de coloane din prima matrice trebuie să se potrivească cu numărul de rânduri din a doua matrice')
result = []
for i in range(matrix1.m):
for j in range(matrix2.n):
val = 0
for k in range(matrix1.n):
val += matrix1.values[i * matrix1.n + k] * matrix2.values[k * matrix2.n + j]
result.append(val)
return Matrix(f'{name1}{name2}', matrix1.m, matrix2.n, result)
def scalar_multiply(self, name, scalar):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> MatrixMultiplier([m1]).scalar_multiply(m1.name, 2)
Matrix(2A, 2, 2, [2, 4, 6, 8])
"""
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = [scalar * val for val in matrix.values]
matrix.values = result
matrix.name = f'{scalar}{name}'
return Matrix(f'{scalar}{name}', matrix.m, matrix.n, result)
def flip_matrix(self, name):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> MatrixMultiplier([m1]).flip_matrix(m1.name)
Matrix(A^T, 2, 2, [1, 3, 2, 4])
"""
matrix = next(matrix for matrix in self.matrices if matrix.name == name)
result = []
for j in range(matrix.n):
for i in range(matrix.m):
result.append(matrix.values[i * matrix.n + j])
matrix.values = result
matrix.m, matrix.n = matrix.n, matrix.m
matrix.name = f'{name}^T'
return matrix
def subtract_matrices(self, name1, name2):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> m2 = Matrix('B', 2, 2, [0, 1, 2, 3])
>>> MatrixMultiplier([m1, m2]).subtract_matrices('A', 'B')
Matrix(A-B, 2, 2, [1, 1, 1, 1])
"""
matrix1 = next(matrix for matrix in self.matrices if matrix.name == name1)
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
if matrix1.m != matrix2.m or matrix1.n != matrix2.n:
raise ValueError('Cele două matrice trebuie să aibă aceleași dimensiuni')
result = [matrix1.values[i] - matrix2.values[i] for i in range(len(matrix1.values))]
return Matrix(f'{name1}-{name2}', matrix1.m, matrix1.n, result)
def proprocess_transpose(self, ops):
"""
>>> m1 = Matrix('A', 2, 2, [1, 2, 3, 4])
>>> mult = MatrixMultiplier([m1])
>>> mult.proprocess_transpose('A t')
'A^T'
>>> mult.matrices[0]
Matrix(A^T, 2, 2, [1, 3, 2, 4])
"""
ops = ops.split()
remove_idxs = []
for i in range(len(ops)):
#print(locals())
if ops[i] == 't':
name = ops[i - 1]
matrix = self.flip_matrix(name)
#print(locals())
name = name + '^T'
#print("matrices", self.matrices)
self.matrices[self.matrices.index(next(m for m in self.matrices if m.name == name))] = matrix
remove_idxs.append(i)
ops[i-1] = f'{name}'
#print("remove_idxs: ", remove_idxs)
ops = [ops[i] for i in range(len(ops)) if i not in remove_idxs]
return ' '.join(ops)
def custom_input(self, ops):
"""
>>> from copy import deepcopy
>>> m1 = Matrix('A', 3, 3, [1, -1, 0, 0, -2, 1, -2, 3, 1])
>>> m2 = Matrix('B', 3, 3, [1, 1,-1, 0, 2, 3, 1, 4, 1])
>>> mult = MatrixMultiplier([deepcopy(m1), deepcopy(m2)])
>>> deepcopy(mult).custom_input('A s 2 - B t')
Matrix(2A-B^T, 3, 3, [1, -2, -1, -1, -6, -2, -3, 3, 1])
>>> mult.custom_input('A t - B t')
Matrix(A^T-B^T, 3, 3, [0, 0, -3, -2, -4, -1, 1, -2, 0])
"""
("Input")
#print(locals())
ops = self.proprocess_transpose(ops)
#print(locals())
ops = ops.split()
#print(locals())
name = ops[0]
#print(locals(), self.matrices)
matrix = next(m for m in self.matrices if m.name == name)
#print(locals())
for i in range(1, len(ops), 2):
#print(locals())
op = ops[i]
if op == 's':
scalar = int(ops[i + 1])
matrix = self.scalar_multiply(matrix.name, scalar)
self.matrices[self.matrices.index(next(m for m in self.matrices if m.name == matrix.name))] = matrix
elif op == '+':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.add_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
elif op == '-':
name2 = ops[i + 1]
matrix2 = next(matrix for matrix in self.matrices if matrix.name == name2)
matrix = self.subtract_matrices(matrix.name, matrix2.name)
self.matrices.append(matrix)
return matrix
if __name__ == "__main__":
doctest.testmod()

So after a lot of research and failed or useless code I managed to solve the problem, yes it was in the input given by the user, namely that it was not divided into groups according to priority, as we all know what is in parentheses in mathematics has priority in solving.
Here is the solution:
def parse_parentheses(self,input_str):
stack = []
term = ""
if "(" in input_str:
for char in input_str:
if char in ['+', '-', '*']:
if term:
stack.append(term)
term = ""
stack.append(char)
elif char == "(":
if term:
stack.append(term)
term = ""
stack.append(char)
elif char == ")":
if term:
stack.append(term)
term = ""
temp = []
while stack and stack[-1] != "(":
temp.append(stack.pop())
if stack[-1] == "(":
stack.pop()
if temp:
stack += temp[::-1]
else:
term += char
if term:
stack.append(term)
for op in ['*', '-', '+']:
while op in stack:
op_index = stack.index(op)
stack.pop(op_index)
stack.append(op)
if op not in stack[op_index + 1:]:
break
return stack
else:
return [input_str]
def custom_input(self, equation):
equation = self.parse_parentheses(equation)
equation_list = []
temp_str = ""
if len(equation)>1:
#IT IS FIXED SO WORKS FOR 2 () sets
_n1 = equation[0][0]
_n2 = equation[1][0]
###################################
for ec in equation:
if ec not in ['+', '-', '*'] and len(ec) > 1:
equation_list.append(ec)
elif ec in ['+', '-', '*']:
equation_list.append(f'{_n1}{ec}{_n2}')
else:
equation_list.append(equation[0])
for equation in equation_list:
if '*' in equation:
matrices = equation.split('*')
matrix1 = next(matrix for matrix in self.matrices if matrix.name == matrices[0])
matrix2 = next(matrix for matrix in self.matrices if matrix.name == matrices[1])
result_matrix = self.multiply_matrices(matrix1.name, matrix2.name)
matrix_name = matrix1.name
elif '-' in equation:
matrices = equation.split('-')
matrix1 = next(matrix for matrix in self.matrices if matrix.name == matrices[0])
matrix2 = next(matrix for matrix in self.matrices if matrix.name == matrices[1])
result_matrix = self.subtract_matrices(matrix1.name, matrix2.name)
matrix_name = matrix1.name
elif 'o' in equation: # SELF MULTIPLY
matrices = equation.split('o')
matrix = next(matrix for matrix in self.matrices if matrix.name == matrices[0])
result_matrix = self.multiply_matrices(matrix.name, matrix.name)
matrix_name = matrix.name
elif 's' in equation:
matrices = equation.split('s')
matrix = next(matrix for matrix in self.matrices if matrix.name == matrices[0])
scalar = float(matrices[1])
result_matrix = self.scalar_multiply(matrix.name, scalar)
matrix_name = matrix.name
elif 't' in equation:
matrix_name = equation.split('t')[0]
matrix = next(matrix for matrix in self.matrices if matrix.name == matrix_name)
result_matrix = self.flip_matrix(matrix.name)
matrix_name = matrix.name
else:
raise ValueError(f"Invalid equation '{equation}'")
if result_matrix is not None:
self.matrices[self.matrices.index(next(matrix for matrix in self.matrices if matrix.name == matrix_name))] = result_matrix
return result_matrix
That would be the solution, of course there are some small or big bugs, but everyone will fix them according to what they need, because in my case it works as it was intended. I want to thanks #Caridorc for the help, the time given and idea's for the solution, thank you once again.
EDIT:
I forgot to tell you, these 2 functions are added to the MatrixMultiplier class and you have to make certain changes in each function of the class, there are certain functions that rename the matrices: scalar_multiply, flip_matrix,
Where you notice the following lines of code:
matrix.values ​​= result
matrix.name = f'{scalar}{name}'
OR
matrix.values ​​= result
matrix.name = f'{name}^T'
Replace with:
matrix.values ​​= result
matrix.name = f'{name}'
FULL CODE HERE: https://pastebin.com/vsAkY8gX

Related

Unable to access float object in a 2D array in Python

I need to return the vector solution x of Ux = b for an upper triangular matrix U and vector b using back substitution, but I'm unable to actually access an element of the matrix U.
def BackSub(U, b):
n = len(U)
x = [0 for i in range(n)]
for i in range(n - 1, -1, -1):
s = 0
for j in range(n - 1, i, -1):
s += (U[i][j])*b[j]
b[i] = (b[i] - s)/(U[i][i])
return b
b = [5, 6, 3, 2]
U = [[ 1, 2, 1, 0],
[ 0, 3, -5, 9],
[ 0, 0, 0.5, 1],
[ 0, 0, 0, 7]]
N = GaussElim(U, b)
x = BackSub(N, b)
It returns
TypeError: 'float' object is not subscriptable for U[i][i]
The GaussElim function is this
import numpy as np
def GaussElim(A, b):
n = len(b) #n is matrix size
#Elimination phase
for k in range(0 , n - 1): #k is matrix row
for i in range(k + 1, n): #i is matrix col
if A[i][k] != 0:
factor = A[i][k]/ A[k][k]
A[i][k + 1 : n] = A[i][k + 1 : n] - np.multiply(factor, A[k][k + 1 : n])
b[i] = b[i] - np.multiply(factor, b[k])
#Back substitution
for k in range(n - 1, -1, -1):
b[k] = (b[k] - dot(A[k][k + 1 : n], b[k + 1 : n]))/A[k][k]
return b

When I have tried to run maze_solver code im not getting the output, how do I get the expected output?

N = 4
def printSolution( sol ):
for i in sol:
for j in i:
print(str(j) + " ", end ="")
print("")
def isSafe( maze, x, y, visited):
if x >= 0 and x < N and y >= 0 and y < N and maze[x][y] == 1 and visited[x][y] == True:
return True
return False
def solveMaze( maze ):
sol = [ [ 0 for j in range(4) ] for i in range(4) ]
visited = [ [ 0 for j in range(4) ] for i in range(4) ]
if solveMazeUtil(maze, 0, 0, sol, visited) == False:
print("Solution doesn't exist")
print(-1)
return False
printSolution(sol)
return True
def solveMazeUtil(maze, x, y, sol, visited):
if x == N - 1 and y == N - 1 and maze[x][y]== 1:
sol[x][y] = 1
return True
if isSafe(maze, x, y, visited) == True:
sol[x][y] = 1
if solveMazeUtil(maze, x + 1, y, sol, visited) == True:
visited[x][y] = True
return True
if solveMazeUtil(maze, x - 1, y, sol, visited) == True:
visited[x][y] = True
return True
if solveMazeUtil(maze, x, y - 1, sol, visited) == True:
visited[x][y] = True
return True
if solveMazeUtil(maze, x, y + 1, sol, visited) == True:
visited[x][y] = True
return True
sol[x][y] = 0
return False
if __name__ == "__main__":
maze = [ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 1, 0] ]
solveMaze(maze)
The following slight changes to your code allows it to work.
Made comments in code to highlight changes.
Code
# N = 4 -- removed (get dimension of maze using len function)
def printSolution( sol ):
for i in sol:
for j in i:
print(str(j) + " ", end ="")
print("")
def isSafe( maze, x, y, visited):
N = len(maze) # Get Maze dimensions (N x M) rather than hardcoding using N as a global
M = len(maze[0])
# x, y safe to use if not visited (original code had visited)
#if x >= 0 and x < N and y >= 0 and y < N and maze[x][y] == 1 and visited[x][y] == True:
# Can simplify x >= 0 and x < N to 0 <= x < M
return 0 <= x < N and 0 <= y < M and maze[x][y] == 1 and not visited[x][y]
def solveMaze( maze ):
N = len(maze) # Get Maze dimensions (N x M) rather than hardcoding using N as a global
M = len(maze[0])
sol = [ [ 0 for j in range(M) ] for i in range(N) ]
visited = [ [ 0 for j in range(M) ] for i in range(N) ]
if not solveMazeUtil(maze, 0, 0, sol, visited): # preferred to checking for False
print("Solution doesn't exist")
print(-1)
return False
printSolution(sol)
return True
def solveMazeUtil(maze, x, y, sol, visited):
N = len(maze) # Get Maze dimensions (N x M) rather than hardcoding using N as a global
M = len(maze[0])
if x == N - 1 and y == M - 1 and maze[x][y]== 1:
sol[x][y] = 1
return True
if isSafe(maze, x, y, visited): # preferred to checking for True
sol[x][y] = 1 # Try solution from current x, y position
visited[x][y] = True # Mark as visited so no other soltuion will use it
# Recursive calls to solveMazeUtil can be simplfied to the following:
if (solveMazeUtil(maze, x + 1, y, sol, visited) or
solveMazeUtil(maze, x - 1, y, sol, visited) or
solveMazeUtil(maze, x, y - 1, sol, visited) or
solveMazeUtil(maze, x, y + 1, sol, visited)):
return True # Found a solution
else:
sol[x][y] = 0 # Couln't use x, y in solution
return False
else:
return False
if __name__ == "__main__":
print("Test 1")
maze = [ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 1, 0] ]
solveMaze(maze)
print("\nTest 2")
maze = [ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 1, 1] ]
solveMaze(maze)
print("\nTest 3")
maze = [ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 1]]
solveMaze(maze)
Output
Test 1
Solution doesn't exist
-1
Test 2
1 0 0 0
1 1 0 0
0 1 0 0
0 1 1 1
Test 3
1 0 0 0
1 1 0 0
0 1 0 0
0 1 0 0
0 1 1 1
OO Version
class Maze:
def __init__(self, maze):
# Constructor
self.maze = maze
def size(self):
# Tuple for Maze dimensions
return len(self.maze), len(self.maze[0])
def isSafe(self, x, y, visited):
'''
Checks if okay to select cell x, y
'''
# Get Maze dimensions (N x M)
N, M = self.size()
# x, y safe to use if not visited (original code had visited)
#if x >= 0 and x < N and y >= 0 and y < N and maze[x][y] == 1 and visited[x][y] == True:
# Can simplify x >= 0 and x < N to 0 <= x < M
return 0 <= x < N and 0 <= y < M and self.maze[x][y] == 1 and not visited[x][y]
def solveMaze(self):
'''
Controlling function for Maze solver
'''
# Get Maze dimensions (N x M)
N, M = self.size()
sol = [ [ 0 for j in range(M) ] for i in range(N) ]
visited = [ [ 0 for j in range(M) ] for i in range(N) ]
if not self.solveMazeUtil(0, 0, sol, visited): # preferred to checking for False
print("Solution doesn't exist")
print(-1)
return False
self.printSolution(sol)
return True
def solveMazeUtil(self, x, y, sol, visited):
'''
Recursive Maze solver
'''
# Get Maze dimensions (N x M)
N, M = self.size()
if x == N - 1 and y == M - 1 and self.maze[x][y]== 1:
sol[x][y] = 1
return True
if self.isSafe(x, y, visited): # preferred to checking for True
sol[x][y] = 1 # Try solution from current x, y position
visited[x][y] = True # Mark as visited so no other soltuion will use it
# Recursive calls to solveMazeUtil can be simplfied to the following:
if (self.solveMazeUtil(x + 1, y, sol, visited) or
self.solveMazeUtil(x - 1, y, sol, visited) or
self.solveMazeUtil(x, y - 1, sol, visited) or
self.solveMazeUtil(x, y + 1, sol, visited)):
return True # Found a solution
else:
sol[x][y] = 0 # Couln't use x, y in solution
return False
else:
return False
def printSolution(self, sol ):
'''
Format and print solution
'''
for i in sol:
for j in i:
print(str(j) + " ", end ="")
print("")
if __name__ == "__main__":
print("Test 1")
maze = Maze([ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 1, 0] ])
maze.solveMaze()
print("\nTest 2")
maze = Maze([ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 1, 1] ])
maze.solveMaze()
print("\nTest 3")
maze = Maze([ [1, 0, 0, 0],
[1, 1, 0, 1],
[0, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 1]])
maze.solveMaze()
Output
Same as non-OO version

I am trying to solve a 6x6 sudoku in Python

I just don't get why i dont get a solution to this?
Can someome point me in the right direction on how to find the solutoion to this?
When i try to input the number 1 - 6 it doesn't work. Just get the print "No Solution", so it skips the solution part of the code.
Thank you so much.
SIZE = 6
# sudoku problem
# 0 is unknown cells
board = [
[0, 6, 0, 0, 0, 0],
[0, 0, 0, 6, 2, 4],
[3, 0, 4, 0, 1, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 0, 4, 5, 0],
[0, 0, 1, 0, 0, 2]]
# function to print sudoku
def print_sudoku():
for i in board:
print(i)
# Function to check if cells are unassigned and to add value to unassigned cells.
def unassigned_numbers(row, col):
unassigned_num: int = 0
for i in range(0, SIZE):
for j in range(0, SIZE):
# cell is unassigned
if board[i][j] == 0:
row = i
col = j
num_unassign = 1
a = [row, col, num_unassign]
return a
a = [-1, -1, unassigned_num]
return a
# function to check if a number can be assign a specific cell
def is_safe(n, r, c):
# checking row
for i in range(0, SIZE):
# Cell has the same value
if board[r][i] == n:
return False
# checking column
for i in range(0, SIZE):
# Cell has the same value
if board[i][c] == n:
return False
row_start = (r // 2) * 3;
col_start = (c // 3) * 2;
# checking box
for i in range(row_start, row_start + 3):
for j in range(col_start, col_start + 2):
if board[i][j] == n:
return False
return True
# Function to check if we can put a value to a given cell
def solve_sudoku():
row = 0
col = 0
# if all cells are assigned then the sudoku is already solved
# pass by reference because number_unassigned will change the values of row and col
a = unassigned_numbers(row, col)
if a[2] == 0:
return True
row = a[0]
col = a[1]
# number between 1 to 6
for i in range(1, 7):
if is_safe(i, row, col):
board[row][col] = i
# backtracking
if solve_sudoku():
return True
# if the solution don't work reassign the cell
board[row][col] = 0
return False
if solve_sudoku():
print_sudoku()
else:
print("No solution")
What can be the issue here?
I am guessing it might be in this part:
checking column
for i in range(0, SIZE):
# Cell has the same value
if board[i][c] == n:
return False
row_start = (r // 2) * 3;
col_start = (c // 3) * 2;
# checking box
for i in range(row_start, row_start + 3):
for j in range(col_start, col_start + 2):
if board[i][j] == n:
return False
return True
Hope someone can help me out :)
Are you sure these calculations are right? Take r=6 for example, this returns a row_start of 6, adding 3 to this index will be out of bounds. Remember you want to check all the numbers in the given box.
(r // 2) * 2
r -> row_start
1 -> 0
2 -> 2
3 -> 2
4 -> 4
5 -> 4
6 -> 6
(c // 3) * 2
c -> col_start
1 -> 0
2 -> 0
3 -> 2
4 -> 2
5 -> 2
6 -> 4

python 3.5.0 :::: MAGIC SQUARE

I'm trying to built a magic square:
A magic square is one divided in rows and columns, with a number in each position and which the sum of rows, columns and diagonals is the same.
Example (3x3 - numbers from 1 to 9):
8 3 4
1 5 9
6 7 2
I tried to use a matrix 3x3 and a vector with 9 indexes.
import random
#j(column)
matriz = [[1, 2, 3],#i(row)
[4, 5, 6],
[7, 8, 9]]
res = False
#DEFINE A FUNCTION TO CALCULATE ALL SUMS OF ALL SIDES
def magicsquare():
if matriz[0][0] + matriz[1][0] + matriz[2][0] == matriz[0][1] + matriz[1][1] + matriz[2][1] == matriz[0][2] + matriz[1][2] + matriz[2][2] == matriz[0][0] + matriz[0][1] + matriz[0][2] == matriz[1][0] + matriz[1][1] + matriz[1][2] == matriz[2][0] + matriz[2][1] + matriz[2][2] == matriz[0][0] + matriz[1][1] + matriz[2][2] == matriz[0][2] + matriz[1][1] + matriz[2][0]:
return res = True
else:
return res = False
#DEFINE A LOOP TO GENERATE RANDOM NUMBER UNTIL FIND THE ONES THAT
#SATISFY THE CONDITIONS OF A MAGIC SQUARE
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
while res == False:
for i in range(2):
for j in range(2):
z = random.choice(seq)
matriz[i][j] = z
x = seq.index(z)
seq[x] = []
magicsquare()
print (matriz)
#---------------------------------------------------------------------------------------------------------------------------------------------------------------
res = False
def magicsquare():
if vetor[0] + vetor[1] + vetor[2] == vetor[3] + vetor[4] + vetor[5] == vetor[6] + vetor[7] + vetor[8] == vetor[0] + vetor[3] + vetor[6] == vetor[1] + vetor[4] + vetor[7] == vetor[2] + vetor[5] + vetor[8] == vetor[0] + vetor[4] + vetor[8] == vetor[2] + vetor[4] + vetor[6]:
return res == True
else:
return res == False
# 0 1 2 3 4 5 6 7 8
vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
if res == False:
for i in range(8):
w = random.choice(seq)
#Replace the value w in index i
vetor.insert(i, w)
#Eliminate the valyes already used
x = seq.index(w)
seq[x] =[]
magicsquare()
print (vetor)
The result is always: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Can anyone help me built a magic square and tell what's wrong with my code?
Using Python 3.5.0
Your randomizing code is wrong.
>>>
Traceback (most recent call last):
File "C:/Users/xiao/Desktop/ms.py", line 20, in <module>
magicsquare()
File "C:/Users/xiao/Desktop/ms.py", line 5, in magicsquare
if vetor[0] + vetor[1] + vetor[2] == vetor[3] + vetor[4] + vetor[5] == vetor[6] + vetor[7] + vetor[8] == vetor[0] + vetor[3] + vetor[6] == vetor[1] + vetor[4] + vetor[7] == vetor[2] + vetor[5] + vetor[8] == vetor[0] + vetor[4] + vetor[8] == vetor[2] + vetor[4] + vetor[6]:
TypeError: unsupported operand type(s) for +: 'int' and 'list'
>>> vetor
[9, 4, 8, 2, 3, [], [], [], 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
random module has a method called shuffle for shuffling a list. If you have no idea about your code, just use random.shuffle.
Plus, there are 2 ways to stop the while loop. The first way is to change the global variable res in function magicsquare:
def magicsquare():
global res
if ...:
res = True
else:
res = False
The other way is to return the condition in magicsquare:
import random
vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def magicsquare():
return vetor[0]+vetor[1]+vetor[2]==\
vetor[3]+vetor[4]+vetor[5]==\
vetor[6]+vetor[7]+vetor[8]==\
vetor[0]+vetor[3]+vetor[6]==\
vetor[1]+vetor[4]+vetor[7]==\
vetor[2]+vetor[5]+vetor[8]==\
vetor[0]+vetor[4]+vetor[8]==\
vetor[2]+vetor[4]+vetor[6]
while not magicsquare():
random.shuffle(vetor)
print (vetor)
def forEvenNumber(n):
arr = [[(n * y) + x + 1 for x in range(n)] for y in range(n)]
for i in range(0, n // 4):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(0, n // 4):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(0, n // 4):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(3 * (n // 4), n):
for j in range(3 * (n // 4), n):
arr[i][j] = (n * n + 1) - arr[i][j];
for i in range(n // 4, 3 * (n // 4)):
for j in range(n // 4, 3 * (n // 4)):
arr[i][j] = (n * n + 1) - arr[i][j];
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(n):
for j in range(n):
print('%2d ' % (arr[i][j]), end=" ")
print()
def forOddNumber(n):
mgsqr = [[0 for x in range(n)]
for y in range(n)]
r = n // 2
c = n - 1
num = 1
while num <= (n * n):
if r == -1 and c == n:
c = n - 2
r = 0
else:
if c == n:
c = 0
if r < 0:
r = n - 1
if mgsqr[int(r)][int(c)]:
c = c - 2
r = r + 1
continue
else:
mgsqr[int(r)][int(c)] = num
num = num + 1
c = c + 1
r = r - 1
print("\nSum of all row, column and diagonals = ",
n * (n * n + 1) // 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (mgsqr[i][j]), end='')
print()
print("\nWELCOME:)\n")
n = int(input("Please Enter Number of Rows and Column (n*n): "))
if n%2==0:
forEvenNumber(n)
else:
forOddNumber(n)
print("\nThank You :)")
try my code..
box = []
num = [1, 2, 3,
4, 5, 6,
7, 8, 9]
val = []
for i in num:
for j in num:
for k in num:
if ((i+j+k) == 15) and i != j and j != k and k != i:
val.append((i, j, k))
def check_sum(lst: list):
rtn = []
res = 0
lst = lst[0]
for c in range(3):
for r in range(3):
res += lst[r][c]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
res = 0
res = 0
for x in range(3):
for y in range(3):
if x == y:
res += lst[x][y]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
res = 0
for x in range(3):
for y in range(3):
if x+y == 2:
res += lst[x][y]
if res == 15:
rtn.append(True)
else:
rtn.append(False)
return all(rtn)
def is_unique(a, b, c):
st = set()
for x in a:
st.add(x)
for x in b:
st.add(x)
for x in c:
st.add(x)
if len(st) == 9:
return True
else:
return False
def print_box(b):
for row in b[0]:
print(row)
print()
for i in val:
for j in val:
for k in val:
if is_unique(i, j, k):
box.append([i, j, k])
if check_sum(box):
print_box(box)
if len(box) == 1:
box.clear()
output is:
(2, 7, 6)
(9, 5, 1)
(4, 3, 8)
(2, 9, 4)
(7, 5, 3)
(6, 1, 8)
(4, 3, 8)
(9, 5, 1)
(2, 7, 6)
(4, 9, 2)
(3, 5, 7)
(8, 1, 6)
(6, 1, 8)
(7, 5, 3)
(2, 9, 4)
(6, 7, 2)
(1, 5, 9)
(8, 3, 4)
(8, 1, 6)
(3, 5, 7)
(4, 9, 2)
(8, 3, 4)
(1, 5, 9)
(6, 7, 2)

Number of pairs

I am trying to write a code that takes
m. a, a list of integers
n. b, an integer
and returns the number of pairs (m,n) with m,n in a such that |m-n|<=b.
So far, I've got this
def nearest_pairs(a, b):
m= []
n= int
num_pairs = 0
return num_pairs
def main():
# The nearest pairs are (1,2), (2,1), (2,5) and (5,2)
x = nearest_pairs( [1,2,5] , 3 )
print( "nearest_pairs([1, 2, 5], 3) = " , nearest_pairs([1, 2, 5], 3) )
# The nearest pairs are (1,2) and (2,1)
y = nearest_pairs( [1, 2, 5] , 2 )
print( "nearest_pairs([1, 2, 5], 2) = " , nearest_pairs([1, 2, 5], 2) )
if __name__ == '__main__':
main()
The desired output should look like
>>> nearest_pairs([1,2,5],3) = 4
where 4 is the number of close pairs according to the restrictions. However, I get an error. Could anyone lead me to the right direction?
Yours doesn't make sense. No idea what you're trying with len(a, b), but it's not even allowed, since len takes only one argument. And returning something just when you found the first counting pair? Here's a fix:
def close_pairs(l, d):
ctr = 0
for a,b in permutations(l, 2):
if (a - b) <= d and (b - a) <= d:
ctr += 1
return ctr
And here's how I'd do it:
def close_pairs(l, d):
return sum(abs(a-b) <= d for a, b in permutations(l, 2))
from itertools import permutations
def nearest_pairs(a, b):
for m, n in permutations(a, 2):
if abs(m - n) <= b:
yield (m, n)
>>> list(nearest_pairs([1, 2, 5], 3))
[(1, 2), (2, 1), (2, 5), (5, 2)]
>>> list(nearest_pairs([1, 2, 5], 2))
[(1, 2), (2, 1)]
If you just want the count:
def nearest_pairs_count(a, b):
c, l = 0, len(a)
for i in range(l):
for j in range(i + 1, l):
if abs(a[i] - a[j]) <= b:
c += 2
return c

Categories