






import copy
import re





class 					A__     :

     '''simple docstring'''






     snake_case__					=					"""hp"""
     snake_case__					=					{}
     snake_case__					=					None







     @classmethod
     def   _SCREAMING_SNAKE_CASE     ( cls      :    Dict   ,						_SCREAMING_SNAKE_CASE      :    Tuple   ,						_SCREAMING_SNAKE_CASE      :    Any ):






           """simple docstring"""




           UpperCamelCase					       =  prefix
           UpperCamelCase					       =  defaults
           cls.build_naming_info()







     @staticmethod
     def   _SCREAMING_SNAKE_CASE     ( _SCREAMING_SNAKE_CASE      :    str   ,						_SCREAMING_SNAKE_CASE      :    Optional[int] ):






           """simple docstring"""




           if len(_SCREAMING_SNAKE_CASE ) == 0:
                 return ""
           UpperCamelCase					       =  None
           if any(char.isdigit() for char in word ):
                 raise Exception(f'Parameters should not contain numbers: \'{word}\' contains a number' )
           if word in info["short_word"]:
                 return info["short_word"][word]
           for prefix_len in range(1   ,						len(_SCREAMING_SNAKE_CASE ) + 1 ):
                 UpperCamelCase					       =  word[:prefix_len]
                 if prefix in info["reverse_short_word"]:
                       continue
                 else:
                       UpperCamelCase					       =  prefix
                       break

           if short_word is None:
                 # Paranoid fallback
                 def int_to_alphabetic(_SCREAMING_SNAKE_CASE      :    Optional[Any] ):
                       UpperCamelCase					       =  ''
                       while integer != 0:
                             UpperCamelCase					       =  chr(ord('A' ) + integer % 10 ) + s
                             integer //= 10
                       return s

                 UpperCamelCase					       =  0
                 while True:
                       UpperCamelCase					       =  word + '#' + int_to_alphabetic(_SCREAMING_SNAKE_CASE )
                       if sword in info["reverse_short_word"]:
                             continue
                       else:
                             UpperCamelCase					       =  sword
                             break

           UpperCamelCase					       =  short_word
           UpperCamelCase					       =  word
           return short_word







     @staticmethod
     def   _SCREAMING_SNAKE_CASE     ( _SCREAMING_SNAKE_CASE      :    str   ,						_SCREAMING_SNAKE_CASE      :    str ):






           """simple docstring"""




           UpperCamelCase					       =  param_name.split('_' )

           UpperCamelCase					       =  [TrialShortNamer.shortname_for_word(_SCREAMING_SNAKE_CASE   ,						_SCREAMING_SNAKE_CASE ) for word in words]

           # We try to create a separatorless short name, but if there is a collision we have to fallback
           # to a separated short name
           UpperCamelCase					       =  ['', '_']

           for separator in separators:
                 UpperCamelCase					       =  separator.join(_SCREAMING_SNAKE_CASE )
                 if shortname not in info["reverse_short_param"]:
                       UpperCamelCase					       =  shortname
                       UpperCamelCase					       =  param_name
                       return shortname

           return param_name







     @staticmethod
     def   _SCREAMING_SNAKE_CASE     ( _SCREAMING_SNAKE_CASE      :    Dict   ,						_SCREAMING_SNAKE_CASE      :    Any ):






           """simple docstring"""




           UpperCamelCase					       =  TrialShortNamer.shortname_for_key(_SCREAMING_SNAKE_CASE   ,						_SCREAMING_SNAKE_CASE )
           UpperCamelCase					       =  short_name
           UpperCamelCase					       =  param_name







     @classmethod
     def   _SCREAMING_SNAKE_CASE     ( cls      :    List[Any] ):






           """simple docstring"""




           if cls.NAMING_INFO is not None:
                 return

           UpperCamelCase					       =  {
               'short_word': {},
               'reverse_short_word': {},
               'short_param': {},
               'reverse_short_param': {},
           }

           UpperCamelCase					       =  list(cls.DEFAULTS.keys() )

           for k in field_keys:
                 cls.add_new_param_name(_SCREAMING_SNAKE_CASE   ,						_SCREAMING_SNAKE_CASE )

           UpperCamelCase					       =  info







     @classmethod
     def   _SCREAMING_SNAKE_CASE     ( cls      :    List[str]   ,						_SCREAMING_SNAKE_CASE      :    Union[str, Any] ):






           """simple docstring"""




           cls.build_naming_info()
           assert cls.PREFIX is not None
           UpperCamelCase					       =  [copy.copy(cls.PREFIX )]

           for k, v in params.items():
                 if k not in cls.DEFAULTS:
                       raise Exception(f'You should provide a default value for the param name {k} with value {v}' )
                 if v == cls.DEFAULTS[k]:
                       # The default value is not added to the name
                       continue

                 UpperCamelCase					       =  cls.NAMING_INFO['short_param'][k]

                 if isinstance(_SCREAMING_SNAKE_CASE   ,						_SCREAMING_SNAKE_CASE ):
                       UpperCamelCase					       =  1 if v else 0

                 UpperCamelCase					       =  '' if isinstance(_SCREAMING_SNAKE_CASE   ,						(int, float) ) else '-'
                 UpperCamelCase					       =  f'{key}{sep}{v}'
                 name.append(_SCREAMING_SNAKE_CASE )

           return "_".join(_SCREAMING_SNAKE_CASE )







     @classmethod
     def   _SCREAMING_SNAKE_CASE     ( cls      :    List[str]   ,						_SCREAMING_SNAKE_CASE      :    Any ):






           """simple docstring"""




           UpperCamelCase					       =  repr[len(cls.PREFIX ) + 1 :]
           if repr == "":
                 UpperCamelCase					       =  []
           else:
                 UpperCamelCase					       =  repr.split('_' )

           UpperCamelCase					       =  {}

           for value in values:
                 if "-" in value:
                       UpperCamelCase       ,  UpperCamelCase					       =  value.split('-' )
                 else:
                       UpperCamelCase					       =  re.sub('[0-9.]'   ,						''   ,						_SCREAMING_SNAKE_CASE )
                       UpperCamelCase					       =  float(re.sub('[^0-9.]'   ,						''   ,						_SCREAMING_SNAKE_CASE ) )

                 UpperCamelCase					       =  cls.NAMING_INFO['reverse_short_param'][p_k]

                 UpperCamelCase					       =  p_v

           for k in cls.DEFAULTS:
                 if k not in parameters:
                       UpperCamelCase					       =  cls.DEFAULTS[k]

           return parameters











from __future__ import annotations

import math
def 		lowercase__  (				_UpperCamelCase       ,							_UpperCamelCase) ->			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 		lowercase__  (				_UpperCamelCase       ,							_UpperCamelCase) ->			Union[str, 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 		lowercase__  (				_UpperCamelCase       ,							_UpperCamelCase) ->			Optional[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 		lowercase__  (				_UpperCamelCase) ->			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 		lowercase__  (				_UpperCamelCase) ->			tuple[int, int]:
      """simple docstring"""

      return len(_UpperCamelCase), len(matrix[0])
def 		lowercase__  (				_UpperCamelCase) ->			None:
      """simple docstring"""

      print('\n'.join(str(_UpperCamelCase) for line in matrix))
def 		lowercase__  (				_UpperCamelCase       ,							_UpperCamelCase) ->			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 		lowercase__  (				_UpperCamelCase       ,							_UpperCamelCase) ->			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__":
       __magic_name__   :  Optional[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],
       ]
       __magic_name__   :  List[str]        =							[[0, 2, 1, 1], [16, 2, 3, 3], [2, 2, 7, 7], [13, 11, 22, 4]]
       print(strassen(matrixa, matrixa))



