
"""simple docstring"""


from __future__ import annotations

import math






def  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__						):
			if len(lowerCAmelCase__						) != 2 or len(a[0]						) != 2 or len(lowerCAmelCase__						) != 2 or len(b[0]						) != 2:
						raise Exception('''Matrices are not 2x2'''						)
			lowerCamelCase_					=  [
			    [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  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__						):
			return [
			    [matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]						)						)]
			    for row in range(len(lowerCAmelCase__						)						)
			]






def  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__						):
			return [
			    [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]						)						)]
			    for row in range(len(lowerCAmelCase__						)						)
			]






def  lowercase						(	lowerCAmelCase__						):
			if len(lowerCAmelCase__						) % 2 != 0 or len(a[0]						) % 2 != 0:
						raise Exception('''Odd matrices are not supported!'''						)

			lowerCamelCase_					=  len(lowerCAmelCase__						)
			lowerCamelCase_					=  matrix_length // 2

			lowerCamelCase_					=  [[a[i][j] for j in range(lowerCAmelCase__	,lowerCAmelCase__						)] for i in range(lowerCAmelCase__						)]
			lowerCamelCase_					=  [
			    [a[i][j] for j in range(lowerCAmelCase__	,lowerCAmelCase__						)] for i in range(lowerCAmelCase__	,lowerCAmelCase__						)
			]

			lowerCamelCase_					=  [[a[i][j] for j in range(lowerCAmelCase__						)] for i in range(lowerCAmelCase__						)]
			lowerCamelCase_					=  [[a[i][j] for j in range(lowerCAmelCase__						)] for i in range(lowerCAmelCase__	,lowerCAmelCase__						)]

			return top_left, top_right, bot_left, bot_right






def  lowercase						(	lowerCAmelCase__						):
			return len(lowerCAmelCase__						), len(matrix[0]						)






def  lowercase						(	lowerCAmelCase__						):
			print('''\n'''.join(str(lowerCAmelCase__						) for line in matrix						)						)






def  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__						):
			if matrix_dimensions(lowerCAmelCase__						) == (2, 2):
						return default_matrix_multiplication(lowerCAmelCase__	,lowerCAmelCase__						)

			lowerCamelCase_		, lowerCamelCase_		, lowerCamelCase_		, lowerCamelCase_					=  split_matrix(lowerCAmelCase__						)
			lowerCamelCase_		, lowerCamelCase_		, lowerCamelCase_		, lowerCamelCase_					=  split_matrix(lowerCAmelCase__						)

			lowerCamelCase_					=  actual_strassen(lowerCAmelCase__	,matrix_subtraction(lowerCAmelCase__	,lowerCAmelCase__						)						)
			lowerCamelCase_					=  actual_strassen(matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)	,lowerCAmelCase__						)
			lowerCamelCase_					=  actual_strassen(matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)	,lowerCAmelCase__						)
			lowerCamelCase_					=  actual_strassen(lowerCAmelCase__	,matrix_subtraction(lowerCAmelCase__	,lowerCAmelCase__						)						)
			lowerCamelCase_					=  actual_strassen(matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)	,matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)						)
			lowerCamelCase_					=  actual_strassen(matrix_subtraction(lowerCAmelCase__	,lowerCAmelCase__						)	,matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)						)
			lowerCamelCase_					=  actual_strassen(matrix_subtraction(lowerCAmelCase__	,lowerCAmelCase__						)	,matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)						)

			lowerCamelCase_					=  matrix_addition(matrix_subtraction(matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)	,lowerCAmelCase__						)	,lowerCAmelCase__						)
			lowerCamelCase_					=  matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)
			lowerCamelCase_					=  matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)
			lowerCamelCase_					=  matrix_subtraction(matrix_subtraction(matrix_addition(lowerCAmelCase__	,lowerCAmelCase__						)	,lowerCAmelCase__						)	,lowerCAmelCase__						)

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






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

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

			lowerCamelCase_					=  max(*lowerCAmelCase__	,*lowerCAmelCase__						)
			lowerCamelCase_					=  int(math.pow(2	,math.ceil(math.loga(lowerCAmelCase__						)						)						)						)
			lowerCamelCase_					=  matrixa
			lowerCamelCase_					=  matrixa

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

			lowerCamelCase_					=  actual_strassen(lowerCAmelCase__	,lowerCAmelCase__						)

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


if __name__ == "__main__":
						A_    							=					[
						    [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],
						]
						A_    							=					[[0, 2, 1, 1], [16, 2, 3, 3], [2, 2, 7, 7], [13, 11, 22, 4]]
						print(strassen(matrixa, matrixa))





"""simple docstring"""


def  lowercase						(	lowerCAmelCase__						):
			lowerCamelCase_					=  generate_pascal_triangle(lowerCAmelCase__						)
			for row_idx in range(lowerCAmelCase__						):
						# Print left spaces
						for _ in range(num_rows - row_idx - 1						):
									print(end=''' '''						)
						# Print row values
						for col_idx in range(row_idx + 1						):
									if col_idx != row_idx:
												print(triangle[row_idx][col_idx]	,end=''' '''						)
									else:
												print(triangle[row_idx][col_idx]	,end=''''''						)
						print()






def  lowercase						(	lowerCAmelCase__						):

			if not isinstance(lowerCAmelCase__	,lowerCAmelCase__						):
						raise TypeError('''The input value of \'num_rows\' should be \'int\''''						)

			if num_rows == 0:
						return []
			elif num_rows < 0:
						raise ValueError(
						    '''The input value of \'num_rows\' should be greater than or equal to 0'''						)

			lowerCamelCase_					=  []
			for current_row_idx in range(lowerCAmelCase__						):
						lowerCamelCase_					=  populate_current_row(lowerCAmelCase__	,lowerCAmelCase__						)
						triangle.append(lowerCAmelCase__						)
			return triangle






def  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__						):
			lowerCamelCase_					=  [-1] * (current_row_idx + 1)
			# first and last elements of current row are equal to 1
			lowerCamelCase_		, lowerCamelCase_					=  1, 1
			for current_col_idx in range(1	,lowerCAmelCase__						):
						calculate_current_element(
						    lowerCAmelCase__	,lowerCAmelCase__	,lowerCAmelCase__	,lowerCAmelCase__						)
			return current_row






def  lowercase						(	lowerCAmelCase__	,lowerCAmelCase__	,lowerCAmelCase__	,lowerCAmelCase__	,):
			lowerCamelCase_					=  triangle[current_row_idx - 1][current_col_idx - 1]
			lowerCamelCase_					=  triangle[current_row_idx - 1][current_col_idx]
			lowerCamelCase_					=  above_to_left_elt + above_to_right_elt






def  lowercase						(	lowerCAmelCase__						):

			if not isinstance(lowerCAmelCase__	,lowerCAmelCase__						):
						raise TypeError('''The input value of \'num_rows\' should be \'int\''''						)

			if num_rows == 0:
						return []
			elif num_rows < 0:
						raise ValueError(
						    '''The input value of \'num_rows\' should be greater than or equal to 0'''						)

			lowerCamelCase_					=  [[1]]

			for row_index in range(1	,lowerCAmelCase__						):
						lowerCamelCase_					=  [0] + result[-1] + [0]
						lowerCamelCase_					=  row_index + 1
						# Calculate the number of distinct elements in a row
						lowerCamelCase_					=  sum(divmod(lowerCAmelCase__	,2						)						)
						lowerCamelCase_					=  [
						    temp_row[i - 1] + temp_row[i] for i in range(1	,distinct_elements + 1						)
						]
						lowerCamelCase_					=  row_first_half[: (row_index + 1) // 2]
						row_second_half.reverse()
						lowerCamelCase_					=  row_first_half + row_second_half
						result.append(lowerCAmelCase__						)

			return result






def  lowercase						(	):
			from collections.abc import Callable
			from timeit import timeit

			def benchmark_a_function(lowerCAmelCase__	,lowerCAmelCase__						) -> None:
						lowerCamelCase_					=  f"{func.__name__}({value})"
						lowerCamelCase_					=  timeit(f"__main__.{call}"	,setup='''import __main__'''						)
						# print(f"{call:38} = {func(value)} -- {timing:.4f} seconds")
						print(f"{call:38} -- {timing:.4f} seconds"						)

			for value in range(15						):  # (1, 7, 14):
						for func in (generate_pascal_triangle, generate_pascal_triangle_optimized):
									benchmark_a_function(lowerCAmelCase__	,lowerCAmelCase__						)
						print()


if __name__ == "__main__":
						import doctest

						doctest.testmod()
						benchmark()



