





import string

import numpy


def _A       (   __magic_name__  , __magic_name__	):
   return b if a == 0 else greatest_common_divisor(b % a  , __magic_name__	)





class  lowerCAmelCase							:
  __lowerCamelCase		=      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)
  __lowerCamelCase		=      numpy.vectorize(lambda lowercase_ : x % 36 )

  __lowerCamelCase		=      numpy.vectorize(lowercase_ )







  def __init__(      self  :Any   ,							_lowercase  :numpy.ndarray ):






     '''simple docstring'''





     lowercase__			       =  self.modulus(_lowercase )  # mod36 calc's on the encrypt key
     self.check_determinant()  # validate the determinant of the encryption key
     lowercase__			       =  encrypt_key.shape[0]







  def   UpperCAmelCase					(      self  :Optional[Any]   ,							_lowercase  :str ):






     '''simple docstring'''





     return self.key_string.index(_lowercase )







  def   UpperCAmelCase					(      self  :int   ,							_lowercase  :int ):






     '''simple docstring'''





     return self.key_string[round(_lowercase )]







  def   UpperCAmelCase					(      self  :List[Any] ):






     '''simple docstring'''





     lowercase__			       =  round(numpy.linalg.det(self.encrypt_key ) )

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

     lowercase__			       =  len(self.key_string )
     if greatest_common_divisor(_lowercase   ,							len(self.key_string ) ) != 1:
        lowercase__			       =  (
            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   UpperCAmelCase					(      self  :Any   ,							_lowercase  :str ):






     '''simple docstring'''





     lowercase__			       =  [char for char in text.upper() if char in self.key_string]

     lowercase__			       =  chars[-1]
     while len(_lowercase ) % self.break_key != 0:
        chars.append(_lowercase )

     return "".join(_lowercase )







  def   UpperCAmelCase					(      self  :Tuple   ,							_lowercase  :str ):






     '''simple docstring'''





     lowercase__			       =  self.process_text(text.upper() )
     lowercase__			       =  ""

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

     return encrypted







  def   UpperCAmelCase					(      self  :int ):






     '''simple docstring'''





     lowercase__			       =  round(numpy.linalg.det(self.encrypt_key ) )

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

     lowercase__			       =  (
         det_inv
         * numpy.linalg.det(self.encrypt_key )
         * numpy.linalg.inv(self.encrypt_key )
     )

     return self.to_int(self.modulus(_lowercase ) )







  def   UpperCAmelCase					(      self  :List[Any]   ,							_lowercase  :str ):






     '''simple docstring'''





     lowercase__			       =  self.make_decrypt_key()
     lowercase__			       =  self.process_text(text.upper() )
     lowercase__			       =  ""

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

     return decrypted


def _A       (   ):
   lowercase__			       =  int(input("Enter the order of the encryption key: "	)	)
   lowercase__			       =  []

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

   lowercase__			       =  HillCipher(numpy.array(__magic_name__	)	)

   print("Would you like to encrypt or decrypt some text? (1 or 2)"	)
   lowercase__			       =  input("\n1. Encrypt\n2. Decrypt\n"	)
   if option == "1":
      lowercase__			       =  input("What text would you like to encrypt?: "	)
      print("Your encrypted text is:"	)
      print(hc.encrypt(__magic_name__	)	)
   elif option == "2":
      lowercase__			       =  input("What text would you like to decrypt?: "	)
      print("Your decrypted text is:"	)
      print(hc.decrypt(__magic_name__	)	)


if __name__ == "__main__":
       import doctest

       doctest.testmod()

       main()













from __future__ import annotations

from collections import deque





class  lowerCAmelCase							:







  def __init__(      self  :List[Any]   ,							_lowercase  :list[str] ):






     '''simple docstring'''





     lowercase__			       =  []
     self.adlist.append(
         {"value": "", "next_states": [], "fail_state": 0, "output": []} )

     for keyword in keywords:
        self.add_keyword(_lowercase )
     self.set_fail_transitions()







  def   UpperCAmelCase					(      self  :str   ,							_lowercase  :int   ,							_lowercase  :str ):






     '''simple docstring'''





     for state in self.adlist[current_state]["next_states"]:
        if char == self.adlist[state]["value"]:
           return state
     return None







  def   UpperCAmelCase					(      self  :List[str]   ,							_lowercase  :str ):






     '''simple docstring'''





     lowercase__			       =  0
     for character in keyword:
        lowercase__			       =  self.find_next_state(_lowercase   ,							_lowercase )
        if next_state is None:
           self.adlist.append(
               {
                   "value": character,
                   "next_states": [],
                   "fail_state": 0,
                   "output": [],
               } )
           self.adlist[current_state]["next_states"].append(len(self.adlist ) - 1 )
           lowercase__			       =  len(self.adlist ) - 1
        else:
           lowercase__			       =  next_state
     self.adlist[current_state]["output"].append(_lowercase )







  def   UpperCAmelCase					(      self  :int ):






     '''simple docstring'''





     lowercase__			       =  deque()
     for node in self.adlist[0]["next_states"]:
        q.append(_lowercase )
        lowercase__			       =  0
     while q:
        lowercase__			       =  q.popleft()
        for child in self.adlist[r]["next_states"]:
           q.append(_lowercase )
           lowercase__			       =  self.adlist[r]["fail_state"]
           while (
               self.find_next_state(_lowercase   ,							self.adlist[child]["value"] ) is None
               and state != 0
           ):
              lowercase__			       =  self.adlist[state]["fail_state"]
           lowercase__			       =  self.find_next_state(
               _lowercase   ,							self.adlist[child]["value"] )
           if self.adlist[child]["fail_state"] is None:
              lowercase__			       =  0
           lowercase__			       =  (
               self.adlist[child]["output"]
               + self.adlist[self.adlist[child]["fail_state"]]["output"]
           )







  def   UpperCAmelCase					(      self  :Optional[Any]   ,							_lowercase  :str ):






     '''simple docstring'''





     lowercase__			       =  {}  # returns a dict with keywords and list of its occurrences
     lowercase__			       =  0
     for i in range(len(_lowercase ) ):
        while (
            self.find_next_state(_lowercase   ,							string[i] ) is None
            and current_state != 0
        ):
           lowercase__			       =  self.adlist[current_state]["fail_state"]
        lowercase__			       =  self.find_next_state(_lowercase   ,							string[i] )
        if next_state is None:
           lowercase__			       =  0
        else:
           lowercase__			       =  next_state
           for key in self.adlist[current_state]["output"]:
              if key not in result:
                 lowercase__			       =  []
              result[key].append(i - len(_lowercase ) + 1 )
     return result


if __name__ == "__main__":
  import doctest

  doctest.testmod()






