
from __future__ import annotations

import math


def 				__A(lowerCAmelCase    ,	lowerCAmelCase			)		->					Optional[int]:

		"""simple docstring"""






		if len(lowercase__			) != 2 or len(a[0]			) != 2 or len(lowercase__			) != 2 or len(b[0]			) != 2:
				raise Exception("""Matrices are not 2x2"""			)
		_UpperCamelCase         =						[
		    [a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
		    [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]],
		]
		return new_matrix


def 				__A(lowerCAmelCase    ,	lowerCAmelCase			)		->					List[str]:

		"""simple docstring"""






		return [
		    [matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]			)			)]
		    for row in range(len(lowercase__			)			)
		]


def 				__A(lowerCAmelCase    ,	lowerCAmelCase			)		->					Any:

		"""simple docstring"""






		return [
		    [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]			)			)]
		    for row in range(len(lowercase__			)			)
		]


def 				__A(lowerCAmelCase			)		->					Optional[int]:

		"""simple docstring"""






		if len(lowercase__			) % 2 != 0 or len(a[0]			) % 2 != 0:
				raise Exception("""Odd matrices are not supported!"""			)

		_UpperCamelCase         =						len(lowercase__			)
		_UpperCamelCase         =						matrix_length // 2

		_UpperCamelCase         =						[[a[i][j] for j in range(lowercase__    ,	lowercase__			)] for i in range(lowercase__			)]
		_UpperCamelCase         =						[
		    [a[i][j] for j in range(lowercase__    ,	lowercase__			)] for i in range(lowercase__    ,	lowercase__			)
		]

		_UpperCamelCase         =						[[a[i][j] for j in range(lowercase__			)] for i in range(lowercase__			)]
		_UpperCamelCase         =						[[a[i][j] for j in range(lowercase__			)] for i in range(lowercase__    ,	lowercase__			)]

		return top_left, top_right, bot_left, bot_right


def 				__A(lowerCAmelCase			)		->					Optional[Any]:

		"""simple docstring"""






		return len(lowercase__			), len(matrix[0]			)


def 				__A(lowerCAmelCase			)		->					List[str]:

		"""simple docstring"""






		print("""\n""".join(str(lowercase__			) for line in matrix			)			)


def 				__A(lowerCAmelCase    ,	lowerCAmelCase			)		->					int:

		"""simple docstring"""






		if matrix_dimensions(lowercase__			) == (2, 2):
				return default_matrix_multiplication(lowercase__    ,	lowercase__			)

		_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase         =						split_matrix(lowercase__			)
		_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase     ,						_UpperCamelCase         =						split_matrix(lowercase__			)

		_UpperCamelCase         =						actual_strassen(lowercase__    ,	matrix_subtraction(lowercase__    ,	lowercase__			)			)
		_UpperCamelCase         =						actual_strassen(matrix_addition(lowercase__    ,	lowercase__			)    ,	lowercase__			)
		_UpperCamelCase         =						actual_strassen(matrix_addition(lowercase__    ,	lowercase__			)    ,	lowercase__			)
		_UpperCamelCase         =						actual_strassen(lowercase__    ,	matrix_subtraction(lowercase__    ,	lowercase__			)			)
		_UpperCamelCase         =						actual_strassen(matrix_addition(lowercase__    ,	lowercase__			)    ,	matrix_addition(lowercase__    ,	lowercase__			)			)
		_UpperCamelCase         =						actual_strassen(matrix_subtraction(lowercase__    ,	lowercase__			)    ,	matrix_addition(lowercase__    ,	lowercase__			)			)
		_UpperCamelCase         =						actual_strassen(matrix_subtraction(lowercase__    ,	lowercase__			)    ,	matrix_addition(lowercase__    ,	lowercase__			)			)

		_UpperCamelCase         =						matrix_addition(matrix_subtraction(matrix_addition(lowercase__    ,	lowercase__			)    ,	lowercase__			)    ,	lowercase__			)
		_UpperCamelCase         =						matrix_addition(lowercase__    ,	lowercase__			)
		_UpperCamelCase         =						matrix_addition(lowercase__    ,	lowercase__			)
		_UpperCamelCase         =						matrix_subtraction(matrix_subtraction(matrix_addition(lowercase__    ,	lowercase__			)    ,	lowercase__			)    ,	lowercase__			)

		# construct the new matrix from our 4 quadrants
		_UpperCamelCase         =						[]
		for i in range(len(lowercase__			)			):
				new_matrix.append(top_left[i] + top_right[i]			)
		for i in range(len(lowercase__			)			):
				new_matrix.append(bot_left[i] + bot_right[i]			)
		return new_matrix


def 				__A(lowerCAmelCase    ,	lowerCAmelCase			)		->					Union[str, Any]:

		"""simple docstring"""






		if matrix_dimensions(lowercase__			)[1] != matrix_dimensions(lowercase__			)[0]:
				_UpperCamelCase         =						(
				    """Unable to multiply these matrices, please check the dimensions.\n"""
				    F'Matrix A: {matrixa}\n'
				    F'Matrix B: {matrixa}'
				)
				raise Exception(lowercase__			)
		_UpperCamelCase         =						matrix_dimensions(lowercase__			)
		_UpperCamelCase         =						matrix_dimensions(lowercase__			)

		if dimensiona[0] == dimensiona[1] and dimensiona[0] == dimensiona[1]:
				return [matrixa, matrixa]

		_UpperCamelCase         =						max(*lowercase__    ,	*lowercase__			)
		_UpperCamelCase         =						int(math.pow(2    ,	math.ceil(math.loga(lowercase__			)			)			)			)
		_UpperCamelCase         =						matrixa
		_UpperCamelCase         =						matrixa

		# Adding zeros to the matrices so that the arrays dimensions are the same and also
		# power of 2
		for i in range(0    ,	lowercase__			):
				if i < dimensiona[0]:
						for _ in range(dimensiona[1]    ,	lowercase__			):
								new_matrixa[i].append(0			)
				else:
						new_matrixa.append([0] * maxim			)
				if i < dimensiona[0]:
						for _ in range(dimensiona[1]    ,	lowercase__			):
								new_matrixa[i].append(0			)
				else:
						new_matrixa.append([0] * maxim			)

		_UpperCamelCase         =						actual_strassen(lowercase__    ,	lowercase__			)

		# Removing the additional zeros
		for i in range(0    ,	lowercase__			):
				if i < dimensiona[0]:
						for _ in range(dimensiona[1]    ,	lowercase__			):
								final_matrix[i].pop()
				else:
						final_matrix.pop()
		return final_matrix


if __name__ == "__main__":
		lowerCamelCase__						=				[
		    [2, 3, 4, 5],
		    [6, 4, 3, 1],
		    [2, 3, 6, 7],
		    [3, 1, 2, 4],
		    [2, 3, 4, 5],
		    [6, 4, 3, 1],
		    [2, 3, 6, 7],
		    [3, 1, 2, 4],
		    [2, 3, 4, 5],
		    [6, 2, 3, 1],
		]
		lowerCamelCase__						=				[[0, 2, 1, 1], [16, 2, 3, 3], [2, 2, 7, 7], [13, 11, 22, 4]]
		print(strassen(matrixa, matrixa))







"""simple docstring"""




def       a_ (	lowercase__ :str,			lowercase__ :int     ):
			return [sentence[i : i + ngram_size] for i in range(len(lowercase__     ) - ngram_size + 1     )]


if __name__ == "__main__":
					from doctest import testmod

					testmod()




