



import string

import numpy



def       lowercase       (   SCREAMING_SNAKE_CASE__       :	int				,       SCREAMING_SNAKE_CASE__       :	int				)  ->     List[str]:
 return b if a == 0 else greatest_common_divisor(b % a				,       _lowerCamelCase				)







class 		snake_case						:



   '''simple docstring'''






   snake_case_					: str          =		string.ascii_uppercase + string.digits
   # This cipher takes alphanumerics into account
   # i.e. a total of 36 characters

   # take x and return x % len(key_string)
   snake_case_					: List[str]          =		numpy.vectorize(lambda SCREAMING_SNAKE_CASE_  : x % 36  )

   snake_case_					: Dict          =		numpy.vectorize(SCREAMING_SNAKE_CASE_  )

   def __init__(					self							:			Optional[Any]				,		lowerCAmelCase							:			Union[str, Any])				->				None:

    """simple docstring"""







    _snake_case    :  Tuple					=					self.modulus(UpperCamelCase__)  # mod36 calc's on the encrypt key
    self.check_determinant()  # validate the determinant of the encryption key
    _snake_case    :  Optional[Any]					=					encrypt_key.shape[0]

   def      UpperCamelCase_  (					self							:			Tuple				,		lowerCAmelCase							:			Union[str, Any])				->				int:

    """simple docstring"""







    return self.key_string.index(UpperCamelCase__)

   def      UpperCamelCase_  (					self							:			Union[str, Any]				,		lowerCAmelCase							:			Optional[Any])				->				str:

    """simple docstring"""







    return self.key_string[round(UpperCamelCase__)]

   def      UpperCamelCase_  (					self							:			Dict)				->				None:

    """simple docstring"""







    _snake_case    :  str					=					round(numpy.linalg.det(self.encrypt_key))

    if det < 0:
     _snake_case    :  Union[str, Any]					=					det % len(self.key_string)

    _snake_case    :  str					=					len(self.key_string)
    if greatest_common_divisor(UpperCamelCase__				,		len(self.key_string)) != 1:
     _snake_case    :  Optional[Any]					=					(
         F'''determinant modular {req_l} of encryption key({det}) '''
         F'''is not co prime w.r.t {req_l}.\nTry another key.'''
     )
     raise ValueError(UpperCamelCase__)

   def      UpperCamelCase_  (					self							:			str				,		lowerCAmelCase							:			str)				->				str:

    """simple docstring"""







    _snake_case    :  List[Any]					=					[char for char in text.upper() if char in self.key_string]

    _snake_case    :  Optional[int]					=					chars[-1]
    while len(UpperCamelCase__) % self.break_key != 0:
     chars.append(UpperCamelCase__)

    return "".join(UpperCamelCase__)

   def      UpperCamelCase_  (					self							:			str				,		lowerCAmelCase							:			int)				->				str:

    """simple docstring"""







    _snake_case    :  Optional[Any]					=					self.process_text(text.upper())
    _snake_case    :  Tuple					=					""""""

    for i in range(0				,		len(UpperCamelCase__) - self.break_key + 1				,		self.break_key):
     _snake_case    :  List[Any]					=					text[i : i + self.break_key]
     _snake_case    :  int					=					[self.replace_letters(UpperCamelCase__) for char in batch]
     _snake_case    :  Optional[int]					=					numpy.array([vec]).T
     _snake_case    :  Optional[Any]					=					self.modulus(self.encrypt_key.dot(UpperCamelCase__)).T.tolist()[
         0
     ]
     _snake_case    :  Any					=					"""""".join(
         self.replace_digits(UpperCamelCase__) for num in batch_encrypted)
     encrypted += encrypted_batch

    return encrypted

   def      UpperCamelCase_  (					self							:			Dict)				->				numpy.ndarray:

    """simple docstring"""







    _snake_case    :  int					=					round(numpy.linalg.det(self.encrypt_key))

    if det < 0:
     _snake_case    :  str					=					det % len(self.key_string)
    _snake_case    :  Dict					=					None
    for i in range(len(self.key_string)):
     if (det * i) % len(self.key_string) == 1:
      _snake_case    :  Dict					=					i
      break

    _snake_case    :  str					=					(
        det_inv
        * numpy.linalg.det(self.encrypt_key)
        * numpy.linalg.inv(self.encrypt_key)
    )

    return self.to_int(self.modulus(UpperCamelCase__))


   def      UpperCamelCase_  (					self							:			Any				,		lowerCAmelCase							:			Any)				->				str:

    """simple docstring"""







    _snake_case    :  List[Any]					=					self.make_decrypt_key()
    _snake_case    :  str					=					self.process_text(text.upper())
    _snake_case    :  Tuple					=					""""""

    for i in range(0				,		len(UpperCamelCase__) - self.break_key + 1				,		self.break_key):
     _snake_case    :  str					=					text[i : i + self.break_key]
     _snake_case    :  Tuple					=					[self.replace_letters(UpperCamelCase__) for char in batch]
     _snake_case    :  List[str]					=					numpy.array([vec]).T
     _snake_case    :  str					=					self.modulus(decrypt_key.dot(UpperCamelCase__)).T.tolist()[0]
     _snake_case    :  List[Any]					=					"""""".join(
         self.replace_digits(UpperCamelCase__) for num in batch_decrypted)
     decrypted += decrypted_batch

    return decrypted



def       lowercase       (   )  ->     List[str]:
 _snake_case    :  Tuple					=					int(input("""Enter the order of the encryption key: """				)				)
 _snake_case    :  str					=					[]

 print("""Enter each row of the encryption key with space separated integers"""				)
 for _ in range(_lowerCamelCase				):
  _snake_case    :  List[Any]					=					[int(_lowerCamelCase				) for x in input().split()]
  hill_matrix.append(_lowerCamelCase				)

 _snake_case    :  Optional[Any]					=					HillCipher(numpy.array(_lowerCamelCase				)				)

 print("""Would you like to encrypt or decrypt some text? (1 or 2)"""				)
 _snake_case    :  Optional[int]					=					input("""\n1. Encrypt\n2. Decrypt\n"""				)
 if option == "1":
  _snake_case    :  List[Any]					=					input("""What text would you like to encrypt?: """				)
  print("""Your encrypted text is:"""				)
  print(hc.encrypt(_lowerCamelCase				)				)
 elif option == "2":
  _snake_case    :  List[Any]					=					input("""What text would you like to decrypt?: """				)
  print("""Your decrypted text is:"""				)
  print(hc.decrypt(_lowerCamelCase				)				)


if __name__ == "__main__":
  import doctest

  doctest.testmod()

  main()










from math import ceil, sqrt



def       lowercase       (   SCREAMING_SNAKE_CASE__       :	int = 1_000_000				)  ->     int:
 _snake_case    :  Tuple					=					0

 for outer_width in range(3				,       (limit // 4) + 2				):
  if outer_width**2 > limit:
   _snake_case    :  int					=					max(ceil(sqrt(outer_width**2 - limit				)				)				,       1				)
  else:
   _snake_case    :  Any					=					1
  if (outer_width - hole_width_lower_bound) % 2:
   hole_width_lower_bound += 1

  answer += (outer_width - hole_width_lower_bound - 2) // 2 + 1

 return answer


if __name__ == "__main__":
  print(F'''{solution() = }''')
