


'''simple docstring'''

import string

import numpy

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


class       a__				:







				"""simple docstring"""



				__UpperCamelCase    :		List[str]	=	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)
				__UpperCamelCase    :		Dict	=	numpy.vectorize(lambda __A      : x % 36      )

				__UpperCamelCase    :		Any	=	numpy.vectorize(__A      )




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




				def 					_snake_case  (self       ,			__lowercase		):
										return self.key_string.index(__lowercase		)




				def 					_snake_case  (self       ,			__lowercase		):
										return self.key_string[round(__lowercase		)]




				def 					_snake_case  (self		):
										__lowerCAmelCase							       =				round(numpy.linalg.det(self.encrypt_key		)		)

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

										__lowerCAmelCase							       =				len(self.key_string		)
										if greatest_common_divisor(__lowercase       ,			len(self.key_string		)		) != 1:
																__lowerCAmelCase							       =				(
																    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 					_snake_case  (self       ,			__lowercase		):
										__lowerCAmelCase							       =				[char for char in text.upper() if char in self.key_string]

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

										return "".join(__lowercase		)




				def 					_snake_case  (self       ,			__lowercase		):
										__lowerCAmelCase							       =				self.process_text(text.upper()		)
										__lowerCAmelCase							       =				''''''

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

										return encrypted




				def 					_snake_case  (self		):
										__lowerCAmelCase							       =				round(numpy.linalg.det(self.encrypt_key		)		)

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

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

										return self.to_int(self.modulus(__lowercase		)		)




				def 					_snake_case  (self       ,			__lowercase		):
										__lowerCAmelCase							       =				self.make_decrypt_key()
										__lowerCAmelCase							       =				self.process_text(text.upper()		)
										__lowerCAmelCase							       =				''''''

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

										return decrypted

def 							__magic_name__(						):
						__lowerCAmelCase							       =				int(input('''Enter the order of the encryption key: '''))
						__lowerCAmelCase							       =				[]

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

						__lowerCAmelCase							       =				HillCipher(numpy.array(lowerCamelCase))

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

from manim import *


class       a__				( __A      ):







				"""simple docstring"""



				def 					_snake_case  (self		):
										__lowerCAmelCase							       =				Rectangle(height=0.5       ,			width=0.5		)
										__lowerCAmelCase							       =				Rectangle(height=0.4_6       ,			width=0.4_6		).set_stroke(width=0		)

										__lowerCAmelCase							       =				[mem.copy() for i in range(6		)]
										__lowerCAmelCase							       =				[mem.copy() for i in range(6		)]
										__lowerCAmelCase							       =				VGroup(*__lowercase		).arrange(__lowercase       ,			buff=0		)
										__lowerCAmelCase							       =				VGroup(*__lowercase		).arrange(__lowercase       ,			buff=0		)
										__lowerCAmelCase							       =				VGroup(__lowercase       ,			__lowercase		).arrange(__lowercase       ,			buff=0		)
										__lowerCAmelCase							       =				Text('''CPU'''       ,			font_size=24		)
										__lowerCAmelCase							       =				Group(__lowercase       ,			__lowercase		).arrange(__lowercase       ,			buff=0.5       ,			aligned_edge=__lowercase		)
										cpu.move_to([-2.5, -0.5, 0]		)
										self.add(__lowercase		)

										__lowerCAmelCase							       =				[mem.copy() for i in range(1		)]
										__lowerCAmelCase							       =				VGroup(*__lowercase		).arrange(__lowercase       ,			buff=0		)
										__lowerCAmelCase							       =				Text('''GPU'''       ,			font_size=24		)
										__lowerCAmelCase							       =				Group(__lowercase       ,			__lowercase		).arrange(__lowercase       ,			buff=0.5       ,			aligned_edge=__lowercase		)
										gpu.align_to(__lowercase       ,			__lowercase		)
										gpu.set_x(gpu.get_x() - 1		)

										self.add(__lowercase		)

										__lowerCAmelCase							       =				[mem.copy() for i in range(6		)]
										__lowerCAmelCase							       =				VGroup(*__lowercase		).arrange(__lowercase       ,			buff=0		)

										__lowerCAmelCase							       =				Text('''Model'''       ,			font_size=24		)
										__lowerCAmelCase							       =				Group(__lowercase       ,			__lowercase		).arrange(__lowercase       ,			buff=0.5       ,			aligned_edge=__lowercase		)
										model.move_to([3, -1.0, 0]		)

										self.play(
										    Create(__lowercase       ,			run_time=1		)       ,			Create(__lowercase       ,			run_time=1		)       ,			Create(__lowercase       ,			run_time=1		)       ,			)

										__lowerCAmelCase							       =				MarkupText(
										    F"""First, an empty model skeleton is loaded\ninto <span fgcolor='{YELLOW}'>memory</span> without using much RAM."""       ,			font_size=24       ,			)

										__lowerCAmelCase							       =				Square(side_length=2.2		)
										key.move_to([-5, 2, 0]		)

										__lowerCAmelCase							       =				MarkupText(
										    F"""<b>Key:</b>\n\n<span fgcolor='{YELLOW}'>●</span> Empty Model"""       ,			font_size=18       ,			)

										key_text.move_to([-5, 2.4, 0]		)

										step_a.move_to([2, 2, 0]		)
										self.play(Write(__lowercase       ,			run_time=2.5		)       ,			Write(__lowercase		)       ,			Write(__lowercase		)		)

										self.add(__lowercase		)

										__lowerCAmelCase							       =				[]
										__lowerCAmelCase							       =				[]
										__lowerCAmelCase							       =				[]
										for i, rect in enumerate(__lowercase		):
																__lowerCAmelCase							       =				Rectangle(height=0.4_6       ,			width=0.4_6		).set_stroke(width=0.0		).set_fill(__lowercase       ,			opacity=0.7		)
																cpu_target.move_to(__lowercase		)
																cpu_target.generate_target()
																__lowerCAmelCase							       =				0.4_6 / 4
																__lowerCAmelCase							       =				0.4_6 / 3

																if i == 0:
																						cpu_target.target.next_to(cpu_left_col_base[0].get_corner(DOWN + LEFT		)       ,			buff=0.0_2       ,			direction=__lowercase		)
																						cpu_target.target.set_x(cpu_target.target.get_x() + 0.1		)
																elif i == 3:
																						cpu_target.target.next_to(cpu_targs[0].target       ,			direction=__lowercase       ,			buff=0.0		)
																else:
																						cpu_target.target.next_to(cpu_targs[i - 1].target       ,			direction=__lowercase       ,			buff=0.0		)
																cpu_targs.append(__lowercase		)

																first_animations.append(rect.animate(run_time=0.5		).set_stroke(__lowercase		)		)
																second_animations.append(MoveToTarget(__lowercase       ,			run_time=1.5		)		)

										self.play(*__lowercase		)
										self.play(*__lowercase		)

										self.wait()

