



from __future__ import annotations

import math





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





def      __snake_case	(			_UpperCAmelCase   , _UpperCAmelCase				):
    return [
        [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]				)				)]
        for row in range(len(snake_case__				)				)
    ]





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

    __a						       =				len(snake_case__				)
    __a						       =				matrix_length // 2

    __a						       =				[[a[i][j] for j in range(snake_case__   , snake_case__				)] for i in range(snake_case__				)]
    __a						       =				[
        [a[i][j] for j in range(snake_case__   , snake_case__				)] for i in range(snake_case__   , snake_case__				)
    ]

    __a						       =				[[a[i][j] for j in range(snake_case__				)] for i in range(snake_case__				)]
    __a						       =				[[a[i][j] for j in range(snake_case__				)] for i in range(snake_case__   , snake_case__				)]

    return top_left, top_right, bot_left, bot_right





def      __snake_case	(			_UpperCAmelCase				):
    return len(snake_case__				), len(matrix[0]				)





def      __snake_case	(			_UpperCAmelCase				):
    print('''\n'''.join(str(snake_case__				) for line in matrix				)				)





def      __snake_case	(			_UpperCAmelCase   , _UpperCAmelCase				):
    if matrix_dimensions(snake_case__				) == (2, 2):
        return default_matrix_multiplication(snake_case__   , snake_case__				)

    __a       ,   __a       ,   __a       ,   __a						       =				split_matrix(snake_case__				)
    __a       ,   __a       ,   __a       ,   __a						       =				split_matrix(snake_case__				)

    __a						       =				actual_strassen(snake_case__   , matrix_subtraction(snake_case__   , snake_case__				)				)
    __a						       =				actual_strassen(matrix_addition(snake_case__   , snake_case__				)   , snake_case__				)
    __a						       =				actual_strassen(matrix_addition(snake_case__   , snake_case__				)   , snake_case__				)
    __a						       =				actual_strassen(snake_case__   , matrix_subtraction(snake_case__   , snake_case__				)				)
    __a						       =				actual_strassen(matrix_addition(snake_case__   , snake_case__				)   , matrix_addition(snake_case__   , snake_case__				)				)
    __a						       =				actual_strassen(matrix_subtraction(snake_case__   , snake_case__				)   , matrix_addition(snake_case__   , snake_case__				)				)
    __a						       =				actual_strassen(matrix_subtraction(snake_case__   , snake_case__				)   , matrix_addition(snake_case__   , snake_case__				)				)

    __a						       =				matrix_addition(matrix_subtraction(matrix_addition(snake_case__   , snake_case__				)   , snake_case__				)   , snake_case__				)
    __a						       =				matrix_addition(snake_case__   , snake_case__				)
    __a						       =				matrix_addition(snake_case__   , snake_case__				)
    __a						       =				matrix_subtraction(matrix_subtraction(matrix_addition(snake_case__   , snake_case__				)   , snake_case__				)   , snake_case__				)

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





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

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

    __a						       =				max(*snake_case__   , *snake_case__				)
    __a						       =				int(math.pow(2   , math.ceil(math.loga(snake_case__				)				)				)				)
    __a						       =				matrixa
    __a						       =				matrixa

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

    __a						       =				actual_strassen(snake_case__   , snake_case__				)

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


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






import math
import sys






def  snake_case  (       snake_case__			:int)						->   int:
       if number != int(snake_case__):
              raise ValueError("""the value of input must be a natural number""")
       if number < 0:
              raise ValueError("""the value of input must not be a negative number""")
       if number == 0:
              return 1
       _A        =  [-1] * (number + 1)
       _A        =  0
       for i in range(1   ,	number + 1):
              _A        =  sys.maxsize
              _A        =  int(math.sqrt(snake_case__))
              for j in range(1   ,	root + 1):
                     _A        =  1 + answers[i - (j**2)]
                     _A        =  min(snake_case__   ,	snake_case__)
              _A        =  answer
       return answers[number]


if __name__ == "__main__":
    import doctest

    doctest.testmod()




