"""simple docstring"""
import string

import numpy







def 						__a   (	_SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )	->int:
  return b if a == 0 else greatest_common_divisor(b % a		,     _SCREAMING_SNAKE_CASE   )




class    __snake_case       :
      a__        =		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)
      a__        =		numpy.vectorize(lambda __lowerCAmelCase				: x % 36				)

      a__        =		numpy.vectorize(__lowerCAmelCase				)



      def __init__(						self    ,			lowercase)	->			None:





        '''simple docstring'''





        a__:     List[str]										=	self.modulus(lowercase)  # mod36 calc's on the encrypt key
        self.check_determinant()  # validate the determinant of the encryption key
        a__:     Dict										=	encrypt_key.shape[0]



      def   lowerCamelCase_   (						self    ,			lowercase)	->			int:





        '''simple docstring'''





        return self.key_string.index(lowercase)



      def   lowerCamelCase_   (						self    ,			lowercase)	->			str:





        '''simple docstring'''





        return self.key_string[round(lowercase)]



      def   lowerCamelCase_   (						self)	->			None:





        '''simple docstring'''





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

        if det < 0:
          a__:     Optional[Any]										=	det % len(self.key_string)

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



      def   lowerCamelCase_   (						self    ,			lowercase)	->			str:





        '''simple docstring'''





        a__:     str										=	[char for char in text.upper() if char in self.key_string]

        a__:     Tuple										=	chars[-1]
        while len(lowercase) % self.break_key != 0:
          chars.append(lowercase)

        return "".join(lowercase)



      def   lowerCamelCase_   (						self    ,			lowercase)	->			str:





        '''simple docstring'''





        a__:     Any										=	self.process_text(text.upper())
        a__:     Optional[int]										=	''

        for i in range(0    ,			len(lowercase) - self.break_key + 1    ,			self.break_key):
          a__:     Union[str, Any]										=	text[i : i + self.break_key]
          a__:     Tuple										=	[self.replace_letters(lowercase) for char in batch]
          a__:     int										=	numpy.array([vec]).T
          a__:     int										=	self.modulus(self.encrypt_key.dot(lowercase)).T.tolist()[
              0
          ]
          a__:     Any										=	''.join(
              self.replace_digits(lowercase) for num in batch_encrypted)
          encrypted += encrypted_batch

        return encrypted



      def   lowerCamelCase_   (						self)	->			numpy.ndarray:





        '''simple docstring'''





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

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

        a__:     int										=	(
            det_inv
            * numpy.linalg.det(self.encrypt_key)
            * numpy.linalg.inv(self.encrypt_key)
        )

        return self.to_int(self.modulus(lowercase))



      def   lowerCamelCase_   (						self    ,			lowercase)	->			str:





        '''simple docstring'''





        a__:     Tuple										=	self.make_decrypt_key()
        a__:     Optional[int]										=	self.process_text(text.upper())
        a__:     str										=	''

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

        return decrypted







def 						__a   (	)	->None:
  a__:     Any										=	int(input('Enter the order of the encryption key: '   )   )
  a__:     List[Any]										=	[]

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

  a__:     Tuple										=	HillCipher(numpy.array(_SCREAMING_SNAKE_CASE   )   )

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


if __name__ == "__main__":
 import doctest

 doctest.testmod()

 main()



"""simple docstring"""
def 						__a   (	_SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )	->Union[str, Any]:
  if height >= 1:
    move_tower(height - 1		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )
    move_disk(_SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )
    move_tower(height - 1		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )







def 						__a   (	_SCREAMING_SNAKE_CASE		,     _SCREAMING_SNAKE_CASE   )	->Union[str, Any]:
  print('moving disk from'		,     _SCREAMING_SNAKE_CASE		,     'to'		,     _SCREAMING_SNAKE_CASE   )







def 						__a   (	)	->List[str]:
  a__:     Dict										=	int(input('Height of hanoi: '   ).strip()   )
  move_tower(_SCREAMING_SNAKE_CASE		,     'A'		,     'B'		,     'C'   )


if __name__ == "__main__":
 main()


