
from __future__ import annotations

import math




def 		A_       (							snake_case							:      List[str]       ,					snake_case							:      Dict       )					->			list:



						'''simple docstring'''

						if len(__UpperCAmelCase       ) != 2 or len(a[0]       ) != 2 or len(__UpperCAmelCase       ) != 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_       (							snake_case							:      Tuple       ,					snake_case							:      Dict       )					->			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(__UpperCAmelCase       )       )
						]




def 		A_       (							snake_case							:      str       ,					snake_case							:      Union[str, Any]       )					->			int:



						'''simple docstring'''

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




def 		A_       (							snake_case							:      int       )					->			tuple[list, list, list, list]:



						'''simple docstring'''

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

						__UpperCamelCase        =	len(__UpperCAmelCase       )
						__UpperCamelCase        =	matrix_length // 2

						__UpperCamelCase        =	[[a[i][j] for j in range(__UpperCAmelCase       ,					__UpperCAmelCase       )] for i in range(__UpperCAmelCase       )]
						__UpperCamelCase        =	[
						    [a[i][j] for j in range(__UpperCAmelCase       ,					__UpperCAmelCase       )] for i in range(__UpperCAmelCase       ,					__UpperCAmelCase       )
						]

						__UpperCamelCase        =	[[a[i][j] for j in range(__UpperCAmelCase       )] for i in range(__UpperCAmelCase       )]
						__UpperCamelCase        =	[[a[i][j] for j in range(__UpperCAmelCase       )] for i in range(__UpperCAmelCase       ,					__UpperCAmelCase       )]

						return top_left, top_right, bot_left, bot_right




def 		A_       (							snake_case							:      Any       )					->			tuple[int, int]:



						'''simple docstring'''

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




def 		A_       (							snake_case							:      str       )					->			None:



						'''simple docstring'''

						print('''\n'''.join(str(__UpperCAmelCase       ) for line in matrix       )       )




def 		A_       (							snake_case							:      Tuple       ,					snake_case							:      List[Any]       )					->			list:



						'''simple docstring'''

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

						__UpperCamelCase     ,							__UpperCamelCase     ,							__UpperCamelCase     ,							__UpperCamelCase        =	split_matrix(__UpperCAmelCase       )
						__UpperCamelCase     ,							__UpperCamelCase     ,							__UpperCamelCase     ,							__UpperCamelCase        =	split_matrix(__UpperCAmelCase       )

						__UpperCamelCase        =	actual_strassen(__UpperCAmelCase       ,					matrix_subtraction(__UpperCAmelCase       ,					__UpperCAmelCase       )       )
						__UpperCamelCase        =	actual_strassen(matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )
						__UpperCamelCase        =	actual_strassen(matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )
						__UpperCamelCase        =	actual_strassen(__UpperCAmelCase       ,					matrix_subtraction(__UpperCAmelCase       ,					__UpperCAmelCase       )       )
						__UpperCamelCase        =	actual_strassen(matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       )
						__UpperCamelCase        =	actual_strassen(matrix_subtraction(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       )
						__UpperCamelCase        =	actual_strassen(matrix_subtraction(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       )

						__UpperCamelCase        =	matrix_addition(matrix_subtraction(matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )
						__UpperCamelCase        =	matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )
						__UpperCamelCase        =	matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )
						__UpperCamelCase        =	matrix_subtraction(matrix_subtraction(matrix_addition(__UpperCAmelCase       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )       ,					__UpperCAmelCase       )

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




def 		A_       (							snake_case							:      Tuple       ,					snake_case							:      int       )					->			list:



						'''simple docstring'''

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

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

						__UpperCamelCase        =	max(*__UpperCAmelCase       ,					*__UpperCAmelCase       )
						__UpperCamelCase        =	int(math.pow(2       ,					math.ceil(math.loga(__UpperCAmelCase       )       )       )       )
						__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       ,					__UpperCAmelCase       ):
												if i < dimensiona[0]:
																		for _ in range(dimensiona[1]       ,					__UpperCAmelCase       ):
																								new_matrixa[i].append(0       )
												else:
																		new_matrixa.append([0] * maxim       )
												if i < dimensiona[0]:
																		for _ in range(dimensiona[1]       ,					__UpperCAmelCase       ):
																								new_matrixa[i].append(0       )
												else:
																		new_matrixa.append([0] * maxim       )

						__UpperCamelCase        =	actual_strassen(__UpperCAmelCase       ,					__UpperCAmelCase       )

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


if __name__ == "__main__":
				lowercase__							:							List[Any]													=	[
				    [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],
				]
				lowercase__							:							Union[str, Any]													=	[[0, 2, 1, 1], [1_6, 2, 3, 3], [2, 2, 7, 7], [1_3, 1_1, 2_2, 4]]
				print(strassen(matrixa, matrixa))










'''simple docstring'''

from __future__ import annotations

import math


def 		__magic_name__    (	__UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	)		->					int:

					'''simple docstring'''

					if depth < 0:
										raise ValueError('''Depth cannot be less than 0'''	)

					if len(__UpperCAmelCase	) == 0:
										raise ValueError('''Scores cannot be empty'''	)

					if depth == height:
										return scores[node_index]

					if is_max:
										return max(
										    minimax(depth + 1,      node_index * 2,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	),      minimax(depth + 1,      node_index * 2 + 1,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	),      )

					return min(
					    minimax(depth + 1,      node_index * 2,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	),      minimax(depth + 1,      node_index * 2 + 1,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	),      )


def 		__magic_name__    (	)		->					None:

					'''simple docstring'''

					snake_case_									=				[90, 23, 6, 33, 21, 65, 123, 3_4423]
					snake_case_									=				math.log(len(__UpperCAmelCase	),      2	)
					print('''Optimal value : ''',      end=''''''	)
					print(minimax(0,      0,      __UpperCAmelCase,      __UpperCAmelCase,      __UpperCAmelCase	)	)


if __name__ == "__main__":
							import doctest

							doctest.testmod()
							main()

