


'''simple docstring'''


import string

import numpy







def      snake_case_  (    SCREAMING_SNAKE_CASE__				, SCREAMING_SNAKE_CASE__	):







				"""simple docstring"""





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





class        lowercase__    :





							'''simple docstring'''


							A_				: Union[str, 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_				: Dict       =    numpy.vectorize(lambda _snake_case   : x % 36   )

							A_				: str       =    numpy.vectorize(_snake_case   )






							def __init__(       self       ,   __snake_case    ):
											_SCREAMING_SNAKE_CASE					:			Tuple							= self.modulus(__snake_case    )  # mod36 calc's on the encrypt key
											self.check_determinant()  # validate the determinant of the encryption key
											_SCREAMING_SNAKE_CASE					:			Optional[Any]							= encrypt_key.shape[0]






							def UpperCAmelCase_      (       self       ,   __snake_case    ):
											return self.key_string.index(__snake_case    )






							def UpperCAmelCase_      (       self       ,   __snake_case    ):
											return self.key_string[round(__snake_case    )]






							def UpperCAmelCase_      (       self    ):
											_SCREAMING_SNAKE_CASE					:			List[str]							= round(numpy.linalg.det(self.encrypt_key    )    )

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

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






							def UpperCAmelCase_      (       self       ,   __snake_case    ):
											_SCREAMING_SNAKE_CASE					:			Dict							= [char for char in text.upper() if char in self.key_string]

											_SCREAMING_SNAKE_CASE					:			Union[str, Any]							= chars[-1]
											while len(__snake_case    ) % self.break_key != 0:
															chars.append(__snake_case    )

											return "".join(__snake_case    )






							def UpperCAmelCase_      (       self       ,   __snake_case    ):
											_SCREAMING_SNAKE_CASE					:			str							= self.process_text(text.upper()    )
											_SCREAMING_SNAKE_CASE					:			List[Any]							= """"""

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

											return encrypted






							def UpperCAmelCase_      (       self    ):
											_SCREAMING_SNAKE_CASE					:			Union[str, Any]							= round(numpy.linalg.det(self.encrypt_key    )    )

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

											_SCREAMING_SNAKE_CASE					:			Any							= (
											    det_inv
											    * numpy.linalg.det(self.encrypt_key    )
											    * numpy.linalg.inv(self.encrypt_key    )
											)

											return self.to_int(self.modulus(__snake_case    )    )






							def UpperCAmelCase_      (       self       ,   __snake_case    ):
											_SCREAMING_SNAKE_CASE					:			List[Any]							= self.make_decrypt_key()
											_SCREAMING_SNAKE_CASE					:			int							= self.process_text(text.upper()    )
											_SCREAMING_SNAKE_CASE					:			Optional[int]							= """"""

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

											return decrypted







def      snake_case_  (    ):







				"""simple docstring"""





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

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

				_SCREAMING_SNAKE_CASE					:			int							= HillCipher(numpy.array(SCREAMING_SNAKE_CASE__	)	)

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


import math







def      snake_case_  (    SCREAMING_SNAKE_CASE__	):







				"""simple docstring"""





				assert isinstance(SCREAMING_SNAKE_CASE__				, SCREAMING_SNAKE_CASE__	) and (
				    number >= 0
				), "'number' must been an int and positive"

				if 1 < number < 4:
								# 2 and 3 are primes
								return True
				elif number < 2 or not number % 2:
								# Negatives, 0, 1 and all even numbers are not primes
								return False

				_SCREAMING_SNAKE_CASE					:			List[str]							= range(3				, int(math.sqrt(SCREAMING_SNAKE_CASE__	) + 1	)				, 2	)
				return not any(not number % i for i in odd_numbers	)







def      snake_case_  (    SCREAMING_SNAKE_CASE__				, SCREAMING_SNAKE_CASE__=1				, **SCREAMING_SNAKE_CASE__	):







				"""simple docstring"""





				_SCREAMING_SNAKE_CASE					:			Dict							= factor * value
				_SCREAMING_SNAKE_CASE					:			Optional[Any]							= value

				while not is_prime(SCREAMING_SNAKE_CASE__	):
								value += 1 if not ("desc" in kwargs and kwargs["desc"] is True) else -1

				if value == first_value_val:
								return next_prime(value + 1				, **SCREAMING_SNAKE_CASE__	)
				return value




