





'''simple docstring'''






from __future__ import annotations

import math
def 							_lowerCamelCase(  UpperCamelCase__    : list    ,       UpperCamelCase__    : list		)		->  list:
    if len(UpperCamelCase__		) != 2 or len(a[0]		) != 2 or len(UpperCamelCase__		) != 2 or len(b[0]		) != 2:
        raise Exception('''Matrices are not 2x2'''		)
    A       :       List[Any]							=						[
        [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 							_lowerCamelCase(  UpperCamelCase__    : list    ,       UpperCamelCase__    : list		)		->  str:
    return [
        [matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]		)		)]
        for row in range(len(UpperCamelCase__		)		)
    ]
def 							_lowerCamelCase(  UpperCamelCase__    : list    ,       UpperCamelCase__    : list		)		->  Optional[Any]:
    return [
        [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]		)		)]
        for row in range(len(UpperCamelCase__		)		)
    ]
def 							_lowerCamelCase(  UpperCamelCase__    : list		)		->  tuple[list, list, list, list]:
    if len(UpperCamelCase__		) % 2 != 0 or len(a[0]		) % 2 != 0:
        raise Exception('''Odd matrices are not supported!'''		)

    A       :       Any							=						len(UpperCamelCase__		)
    A       :       Optional[Any]							=						matrix_length // 2

    A       :       Dict							=						[[a[i][j] for j in range(UpperCamelCase__    ,       UpperCamelCase__		)] for i in range(UpperCamelCase__		)]
    A       :       Union[str, Any]							=						[
        [a[i][j] for j in range(UpperCamelCase__    ,       UpperCamelCase__		)] for i in range(UpperCamelCase__    ,       UpperCamelCase__		)
    ]

    A       :       Optional[Any]							=						[[a[i][j] for j in range(UpperCamelCase__		)] for i in range(UpperCamelCase__		)]
    A       :       Union[str, Any]							=						[[a[i][j] for j in range(UpperCamelCase__		)] for i in range(UpperCamelCase__    ,       UpperCamelCase__		)]

    return top_left, top_right, bot_left, bot_right
def 							_lowerCamelCase(  UpperCamelCase__    : list		)		->  tuple[int, int]:
    return len(UpperCamelCase__		), len(matrix[0]		)
def 							_lowerCamelCase(  UpperCamelCase__    : list		)		->  None:
    print('''\n'''.join(str(UpperCamelCase__		) for line in matrix		)		)
def 							_lowerCamelCase(  UpperCamelCase__    : list    ,       UpperCamelCase__    : list		)		->  list:
    if matrix_dimensions(UpperCamelCase__		) == (2, 2):
        return default_matrix_multiplication(UpperCamelCase__    ,       UpperCamelCase__		)

    A       :       Optional[Any]							=						split_matrix(UpperCamelCase__		)
    A       :       List[str]							=						split_matrix(UpperCamelCase__		)

    A       :       Union[str, Any]							=						actual_strassen(UpperCamelCase__    ,       matrix_subtraction(UpperCamelCase__    ,       UpperCamelCase__		)		)
    A       :       Dict							=						actual_strassen(matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)
    A       :       int							=						actual_strassen(matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)
    A       :       str							=						actual_strassen(UpperCamelCase__    ,       matrix_subtraction(UpperCamelCase__    ,       UpperCamelCase__		)		)
    A       :       Union[str, Any]							=						actual_strassen(matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)    ,       matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)		)
    A       :       Tuple							=						actual_strassen(matrix_subtraction(UpperCamelCase__    ,       UpperCamelCase__		)    ,       matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)		)
    A       :       Any							=						actual_strassen(matrix_subtraction(UpperCamelCase__    ,       UpperCamelCase__		)    ,       matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)		)

    A       :       int							=						matrix_addition(matrix_subtraction(matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)
    A       :       Optional[int]							=						matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)
    A       :       Optional[Any]							=						matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)
    A       :       Dict							=						matrix_subtraction(matrix_subtraction(matrix_addition(UpperCamelCase__    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)    ,       UpperCamelCase__		)

    # construct the new matrix from our 4 quadrants
    A       :       int							=						[]
    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 							_lowerCamelCase(  UpperCamelCase__    : list    ,       UpperCamelCase__    : list		)		->  list:
    if matrix_dimensions(UpperCamelCase__		)[1] != matrix_dimensions(UpperCamelCase__		)[0]:
        A       :       Tuple							=						(
            '''Unable to multiply these matrices, please check the dimensions.\n'''
            F'''Matrix A: {matrixa}\n'''
            F'''Matrix B: {matrixa}'''
        )
        raise Exception(UpperCamelCase__		)
    A       :       Optional[Any]							=						matrix_dimensions(UpperCamelCase__		)
    A       :       List[str]							=						matrix_dimensions(UpperCamelCase__		)

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

    A       :       List[Any]							=						max(*UpperCamelCase__    ,       *UpperCamelCase__		)
    A       :       int							=						int(math.pow(2    ,       math.ceil(math.loga(UpperCamelCase__		)		)		)		)
    A       :       int							=						matrixa
    A       :       Any							=						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		)

    A       :       Dict							=						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__":
     snake_case_     =	[
         [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_     =	[[0, 2, 1, 1], [16, 2, 3, 3], [2, 2, 7, 7], [13, 11, 22, 4]]
     print(strassen(matrixa, matrixa))








'''simple docstring'''






def 							_lowerCamelCase(  UpperCamelCase__    : int		)		->  None:
    A       :       List[Any]							=						generate_pascal_triangle(UpperCamelCase__		)
    for row_idx in range(UpperCamelCase__		):
        # 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 							_lowerCamelCase(  UpperCamelCase__    : int		)		->  list[list[int]]:

    if not isinstance(UpperCamelCase__    ,       UpperCamelCase__		):
        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'''		)

    A       :       list[list[int]]							=						[]
    for current_row_idx in range(UpperCamelCase__		):
        A       :       Optional[int]							=						populate_current_row(UpperCamelCase__    ,       UpperCamelCase__		)
        triangle.append(UpperCamelCase__		)
    return triangle
def 							_lowerCamelCase(  UpperCamelCase__    : list[list[int]]    ,       UpperCamelCase__    : int		)		->  list[int]:
    A       :       Dict							=						[-1] * (current_row_idx + 1)
    # first and last elements of current row are equal to 1
    A,	A       :       Union[str, Any]							=						1, 1
    for current_col_idx in range(1    ,       UpperCamelCase__		):
        calculate_current_element(
            UpperCamelCase__    ,       UpperCamelCase__    ,       UpperCamelCase__    ,       UpperCamelCase__		)
    return current_row
def 							_lowerCamelCase(  UpperCamelCase__    : list[list[int]]    ,       UpperCamelCase__    : list[int]    ,       UpperCamelCase__    : int    ,       UpperCamelCase__    : int    ,       )		->  None:
    A       :       Dict							=						triangle[current_row_idx - 1][current_col_idx - 1]
    A       :       Any							=						triangle[current_row_idx - 1][current_col_idx]
    A       :       Optional[int]							=						above_to_left_elt + above_to_right_elt
def 							_lowerCamelCase(  UpperCamelCase__    : int		)		->  list[list[int]]:

    if not isinstance(UpperCamelCase__    ,       UpperCamelCase__		):
        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'''		)

    A       :       list[list[int]]							=						[[1]]

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

    return result
def 							_lowerCamelCase(  )		->  None:
    from collections.abc import Callable
    from timeit import timeit

    def benchmark_a_function(UpperCamelCase__    : Callable    ,       UpperCamelCase__    : int		) -> None:
        A       :       Dict							=						F'''{func.__name__}({value})'''
        A       :       List[Any]							=						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(UpperCamelCase__    ,       UpperCamelCase__		)
        print()


if __name__ == "__main__":
     import doctest

     doctest.testmod()
     benchmark()
