



'''simple docstring'''
import string

import numpy


def      lowercase_		(      lowerCAmelCase__		:     Union[str, Any]	,							lowerCAmelCase__		:     List[Any]       ):

			"""simple docstring"""





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



class _A     :
		_SCREAMING_SNAKE_CASE    :			Optional[int]  					=	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)
		_SCREAMING_SNAKE_CASE    :			int  					=	numpy.vectorize(lambda __SCREAMING_SNAKE_CASE			: x % 36			)

		_SCREAMING_SNAKE_CASE    :			Optional[int]  					=	numpy.vectorize(SCREAMING_SNAKE_CASE_			)





		def __init__(   self       ,				__UpperCAmelCase )				->   None:

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





		def 							__A				(   self       ,				__UpperCAmelCase )				->   int:

					'''simple docstring'''
					return self.key_string.index(_a )





		def 							__A				(   self       ,				__UpperCAmelCase )				->   str:

					'''simple docstring'''
					return self.key_string[round(_a )]





		def 							__A				(   self )				->   None:

					'''simple docstring'''
					__UpperCAmelCase      :					Union[str, Any]   =   round(numpy.linalg.det(self.encrypt_key ) )

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

					__UpperCAmelCase      :					Tuple   =   len(self.key_string )
					if greatest_common_divisor(_a       ,				len(self.key_string ) ) != 1:
								__UpperCAmelCase      :					Union[str, 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(_a )





		def 							__A				(   self       ,				__UpperCAmelCase )				->   str:

					'''simple docstring'''
					__UpperCAmelCase      :					Optional[int]   =   [char for char in text.upper() if char in self.key_string]

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

					return "".join(_a )





		def 							__A				(   self       ,				__UpperCAmelCase )				->   str:

					'''simple docstring'''
					__UpperCAmelCase      :					Tuple   =   self.process_text(text.upper() )
					__UpperCAmelCase      :					Dict   =   ''

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

					return encrypted





		def 							__A				(   self )				->   numpy.ndarray:

					'''simple docstring'''
					__UpperCAmelCase      :					Dict   =   round(numpy.linalg.det(self.encrypt_key ) )

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

					__UpperCAmelCase      :					Dict   =   (
					    det_inv
					    * numpy.linalg.det(self.encrypt_key )
					    * numpy.linalg.inv(self.encrypt_key )
					)

					return self.to_int(self.modulus(_a ) )





		def 							__A				(   self       ,				__UpperCAmelCase )				->   str:

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

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

					return decrypted


def      lowercase_		(      ):

			"""simple docstring"""





			__UpperCAmelCase      :					List[Any]   =   int(input("""Enter the order of the encryption key: """       )       )
			__UpperCAmelCase      :					Tuple   =   []

			print("""Enter each row of the encryption key with space separated integers"""       )
			for _ in range(_lowerCAmelCase       ):
						__UpperCAmelCase      :					Union[str, Any]   =   [int(_lowerCAmelCase       ) for x in input().split()]
						hill_matrix.append(_lowerCAmelCase       )

			__UpperCAmelCase      :					List[str]   =   HillCipher(numpy.array(_lowerCAmelCase       )       )

			print("""Would you like to encrypt or decrypt some text? (1 or 2)"""       )
			__UpperCAmelCase      :					str   =   input("""\n1. Encrypt\n2. Decrypt\n"""       )
			if option == "1":
						__UpperCAmelCase      :					Optional[int]   =   input("""What text would you like to encrypt?: """       )
						print("""Your encrypted text is:"""       )
						print(hc.encrypt(_lowerCAmelCase       )       )
			elif option == "2":
						__UpperCAmelCase      :					List[str]   =   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()









'''simple docstring'''





def        a_     (							_lowerCAmelCase       )      ->      str:
  if not all(char in '01' for char in bin_string       ):
    raise ValueError('Non-binary value was passed to the function'       )
  if not bin_string:
    raise ValueError('Empty string was passed to the function'       )
  __lowerCamelCase       :       int           = ''
  while len(_lowerCAmelCase       ) % 3 != 0:
    __lowerCamelCase       :       str           = '0' + bin_string
  __lowerCamelCase       :       Union[str, Any]           = [
      bin_string[index : index + 3]
      for index in range(len(_lowerCAmelCase       )       )
      if index % 3 == 0
  ]
  for bin_group in bin_string_in_3_list:
    __lowerCamelCase       :       Tuple           = 0
    for index, val in enumerate(_lowerCAmelCase       ):
      oct_val += int(2 ** (2 - index) * int(_lowerCAmelCase       )       )
    oct_string += str(_lowerCAmelCase       )
  return oct_string


if __name__ == "__main__":
   from doctest import testmod

   testmod()






