





import string

import numpy





def      lowerCAmelCase_ (       __a	,    __a		)     ->		int:







  """simple docstring"""





  return b if a == 0 else greatest_common_divisor(b % a	,    __a		)



class    _SCREAMING_SNAKE_CASE						:







 '''simple docstring'''
 lowercase_		=			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)
 lowercase_		=			numpy.vectorize(lambda __SCREAMING_SNAKE_CASE    : x % 36    )

 lowercase_		=			numpy.vectorize(__SCREAMING_SNAKE_CASE    )

 def __init__(self				:   Union[str, Any]       , UpperCAmelCase_				:   numpy.ndarray)       ->None:



   '''simple docstring'''



   lowerCamelCase__:      int			  =self.modulus(UpperCAmelCase_)  # mod36 calc's on the encrypt key
   self.check_determinant()  # validate the determinant of the encryption key
   lowerCamelCase__:      Dict			  =encrypt_key.shape[0]

 def 							SCREAMING_SNAKE_CASE_					(self				:   str       , UpperCAmelCase_				:   str)       ->int:



   '''simple docstring'''



   return self.key_string.index(UpperCAmelCase_)

 def 							SCREAMING_SNAKE_CASE_					(self				:   Any       , UpperCAmelCase_				:   int)       ->str:



   '''simple docstring'''



   return self.key_string[round(UpperCAmelCase_)]

 def 							SCREAMING_SNAKE_CASE_					(self				:   int)       ->None:



   '''simple docstring'''



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

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

   lowerCamelCase__:      Optional[int]			  =len(self.key_string)
   if greatest_common_divisor(UpperCAmelCase_       , len(self.key_string)) != 1:
     lowerCamelCase__:      Tuple			  =(
         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 							SCREAMING_SNAKE_CASE_					(self				:   Optional[int]       , UpperCAmelCase_				:   str)       ->str:



   '''simple docstring'''



   lowerCamelCase__:      int			  =[char for char in text.upper() if char in self.key_string]

   lowerCamelCase__:      List[str]			  =chars[-1]
   while len(UpperCAmelCase_) % self.break_key != 0:
     chars.append(UpperCAmelCase_)

   return "".join(UpperCAmelCase_)

 def 							SCREAMING_SNAKE_CASE_					(self				:   Tuple       , UpperCAmelCase_				:   str)       ->str:



   '''simple docstring'''



   lowerCamelCase__:      Any			  =self.process_text(text.upper())
   lowerCamelCase__:      List[str]			  =""

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

   return encrypted

 def 							SCREAMING_SNAKE_CASE_					(self				:   List[str])       ->numpy.ndarray:



   '''simple docstring'''



   lowerCamelCase__:      Tuple			  =round(numpy.linalg.det(self.encrypt_key))

   if det < 0:
     lowerCamelCase__:      str			  =det % len(self.key_string)
   lowerCamelCase__:      Optional[int]			  =None
   for i in range(len(self.key_string)):
     if (det * i) % len(self.key_string) == 1:
       lowerCamelCase__:      Optional[int]			  =i
       break

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

   return self.to_int(self.modulus(UpperCAmelCase_))







 def 							SCREAMING_SNAKE_CASE_					(self				:   Optional[Any]       , UpperCAmelCase_				:   str)       ->str:



   '''simple docstring'''



   lowerCamelCase__:      Any			  =self.make_decrypt_key()
   lowerCamelCase__:      Any			  =self.process_text(text.upper())
   lowerCamelCase__:      Dict			  =""

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

   return decrypted





def      lowerCAmelCase_ (       )     ->		None:







  """simple docstring"""





  lowerCamelCase__:      Optional[Any]			  =int(input("Enter the order of the encryption key: "		)		)
  lowerCamelCase__:      str			  =[]

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

  lowerCamelCase__:      Dict			  =HillCipher(numpy.array(__a		)		)

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


if __name__ == "__main__":
     import doctest

     doctest.testmod()

     main()








import os


# All paths are set with the intent you should run this script from the root of the repo with the command
# python utils/check_doctest_list.py
__A									=				"."


if __name__ == "__main__":
     __A									=				os.path.join(REPO_PATH, "utils/documentation_tests.txt")
     __A									=				[]
     __A									=				[]
     with open(doctest_file_path) as fp:
          for line in fp:
               __A									=				line.strip()
               __A									=				os.path.join(REPO_PATH, line)
               if not (os.path.isfile(path) or os.path.isdir(path)):
                    non_existent_paths.append(line)
               all_paths.append(path)
     if len(non_existent_paths) > 0:
          __A									=				"\n".join(non_existent_paths)
          raise ValueError(f'`utils/documentation_tests.txt` contains non-existent paths:\n{non_existent_paths}')
     if all_paths != sorted(all_paths):
          raise ValueError("Files in `utils/documentation_tests.txt` are not in alphabetical order.")

