





import string

import numpy




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






class     lowercase__       :

   '''simple docstring'''


   a						:							List[Any]   		=		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						:							Optional[int]   		=		numpy.vectorize(lambda __lowerCamelCase				: x % 36				)

   a						:							Union[str, Any]   		=		numpy.vectorize(__lowerCamelCase				)




   def __init__(    self,		__magic_name__							) ->      None:






       """simple docstring"""
       UpperCamelCase__							:				Union[str, Any]          =      self.modulus(__magic_name__							)  # mod36 calc's on the encrypt key
       self.check_determinant()  # validate the determinant of the encryption key
       UpperCamelCase__							:				Optional[Any]          =      encrypt_key.shape[0]




   def       UpperCamelCase__  (    self,		__magic_name__							) ->      int:






       """simple docstring"""
       return self.key_string.index(__magic_name__							)




   def       UpperCamelCase__  (    self,		__magic_name__							) ->      str:






       """simple docstring"""
       return self.key_string[round(__magic_name__							)]




   def       UpperCamelCase__  (    self							) ->      None:






       """simple docstring"""
       UpperCamelCase__							:				Any          =      round(numpy.linalg.det(self.encrypt_key							)							)

       if det < 0:
           UpperCamelCase__							:				str          =      det % len(self.key_string							)

       UpperCamelCase__							:				List[Any]          =      len(self.key_string							)
       if greatest_common_divisor(__magic_name__,		len(self.key_string							)							) != 1:
           UpperCamelCase__							:				Dict          =      (
               f"determinant modular {req_l} of encryption key({det}) "
               f"is not co prime w.r.t {req_l}.\nTry another key."
           )
           raise ValueError(__magic_name__							)




   def       UpperCamelCase__  (    self,		__magic_name__							) ->      str:






       """simple docstring"""
       UpperCamelCase__							:				Any          =      [char for char in text.upper() if char in self.key_string]

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

       return "".join(__magic_name__							)




   def       UpperCamelCase__  (    self,		__magic_name__							) ->      str:






       """simple docstring"""
       UpperCamelCase__							:				int          =      self.process_text(text.upper()							)
       UpperCamelCase__							:				List[Any]          =      ''''''

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

       return encrypted




   def       UpperCamelCase__  (    self							) ->      numpy.ndarray:






       """simple docstring"""
       UpperCamelCase__							:				int          =      round(numpy.linalg.det(self.encrypt_key							)							)

       if det < 0:
           UpperCamelCase__							:				List[Any]          =      det % len(self.key_string							)
       UpperCamelCase__							:				Any          =      None
       for i in range(len(self.key_string							)							):
           if (det * i) % len(self.key_string							) == 1:
               UpperCamelCase__							:				Any          =      i
               break

       UpperCamelCase__							:				Optional[Any]          =      (
           det_inv
           * numpy.linalg.det(self.encrypt_key							)
           * numpy.linalg.inv(self.encrypt_key							)
       )

       return self.to_int(self.modulus(__magic_name__							)							)




   def       UpperCamelCase__  (    self,		__magic_name__							) ->      str:






       """simple docstring"""
       UpperCamelCase__							:				Union[str, Any]          =      self.make_decrypt_key()
       UpperCamelCase__							:				Tuple          =      self.process_text(text.upper()							)
       UpperCamelCase__							:				Dict          =      ''''''

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

       return decrypted




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

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

    UpperCamelCase__							:				Optional[Any]          =      HillCipher(numpy.array(__UpperCAmelCase      )      )

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


if __name__ == "__main__":
  import doctest

  doctest.testmod()

  main()








from __future__ import annotations




def 		lowerCAmelCase_    (  __UpperCAmelCase:			int		,   __UpperCAmelCase:			int      )      ->	list[list[int]]:
    UpperCamelCase__							:				list[list[int]]          =      []
    create_all_state(1		,   __UpperCAmelCase		,   __UpperCAmelCase		,   []		,   __UpperCAmelCase      )
    return result




def 		lowerCAmelCase_    (  __UpperCAmelCase:			int		,   __UpperCAmelCase:			int		,   __UpperCAmelCase:			int		,   __UpperCAmelCase:			list[int]		,   __UpperCAmelCase:			list[list[int]]		,   )      ->	None:
    if level == 0:
        total_list.append(current_list[:]      )
        return

    for i in range(__UpperCAmelCase		,   total_number - level + 2      ):
        current_list.append(__UpperCAmelCase      )
        create_all_state(i + 1		,   __UpperCAmelCase		,   level - 1		,   __UpperCAmelCase		,   __UpperCAmelCase      )
        current_list.pop()




def 		lowerCAmelCase_    (  __UpperCAmelCase:			list[list[int]]      )      ->	None:
    for i in total_list:
        print(*__UpperCAmelCase      )


if __name__ == "__main__":
  UpperCAmelCase_     							= 4
  UpperCAmelCase_     							= 2
  UpperCAmelCase_     							= generate_all_combinations(n, k)
  print_all_state(total_list)

