






'''simple docstring'''







import string

import numpy





def 				SCREAMING_SNAKE_CASE_ (UpperCamelCase       ,    UpperCamelCase   )   -> int:
							return b if a == 0 else greatest_common_divisor(b % a       ,    UpperCamelCase   )

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

							a          = numpy.vectorize(_lowercase	)




							def __init__(							self:       Tuple    ,							UpperCamelCase__:       numpy.ndarray  ):
														lowerCamelCase__      :			Optional[int] 						= self.modulus(UpperCamelCase__  )  # mod36 calc's on the encrypt key
														self.check_determinant()  # validate the determinant of the encryption key
														lowerCamelCase__      :			List[str] 						= encrypt_key.shape[0]




							def 	lowerCamelCase_       (							self:       Any    ,							UpperCamelCase__:       str  ):
														return self.key_string.index(UpperCamelCase__  )




							def 	lowerCamelCase_       (							self:       Tuple    ,							UpperCamelCase__:       int  ):
														return self.key_string[round(UpperCamelCase__  )]




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

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

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




							def 	lowerCamelCase_       (							self:       Optional[Any]    ,							UpperCamelCase__:       str  ):
														lowerCamelCase__      :			int 						= [char for char in text.upper() if char in self.key_string]

														lowerCamelCase__      :			Optional[int] 						= chars[-1]
														while len(UpperCamelCase__  ) % self.break_key != 0:
																					chars.append(UpperCamelCase__  )

														return "".join(UpperCamelCase__  )




							def 	lowerCamelCase_       (							self:       str    ,							UpperCamelCase__:       str  ):
														lowerCamelCase__      :			List[Any] 						= self.process_text(text.upper()  )
														lowerCamelCase__      :			Optional[Any] 						= """"""

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

														return encrypted




							def 	lowerCamelCase_       (							self:       Optional[Any]  ):
														lowerCamelCase__      :			List[Any] 						= round(numpy.linalg.det(self.encrypt_key  )  )

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

														lowerCamelCase__      :			Optional[Any] 						= (
														    det_inv
														    * numpy.linalg.det(self.encrypt_key  )
														    * numpy.linalg.inv(self.encrypt_key  )
														)

														return self.to_int(self.modulus(UpperCamelCase__  )  )




							def 	lowerCamelCase_       (							self:       Tuple    ,							UpperCamelCase__:       str  ):
														lowerCamelCase__      :			Tuple 						= self.make_decrypt_key()
														lowerCamelCase__      :			Union[str, Any] 						= self.process_text(text.upper()  )
														lowerCamelCase__      :			str 						= """"""

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

														return decrypted





def 				SCREAMING_SNAKE_CASE_ ()   -> None:
							lowerCamelCase__      :			List[str] 						= int(input("""Enter the order of the encryption key: """   )   )
							lowerCamelCase__      :			Union[str, Any] 						= []

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

							lowerCamelCase__      :			List[str] 						= HillCipher(numpy.array(UpperCamelCase   )   )

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


if __name__ == "__main__":
			import doctest

			doctest.testmod()

			main()









'''simple docstring'''







from statistics import mean

import numpy as np





def 				SCREAMING_SNAKE_CASE_ (UpperCamelCase       ,    UpperCamelCase       ,    UpperCamelCase       ,    UpperCamelCase   )   -> list:
							lowerCamelCase__      :			Optional[int] 						= 0
							# Number of processes finished
							lowerCamelCase__      :			Union[str, Any] 						= 0
							# Displays the finished process.
							# If it is 0, the performance is completed if it is 1, before the performance.
							lowerCamelCase__      :			Tuple 						= [0] * no_of_process
							# List to include calculation results
							lowerCamelCase__      :			List[str] 						= [0] * no_of_process

							# Sort by arrival time.
							lowerCamelCase__      :			Union[str, Any] 						= [burst_time[i] for i in np.argsort(UpperCamelCase   )]
							lowerCamelCase__      :			List[Any] 						= [process_name[i] for i in np.argsort(UpperCamelCase   )]
							arrival_time.sort()

							while no_of_process > finished_process_count:
														lowerCamelCase__      :			str 						= 0
														while finished_process[i] == 1:
																					i += 1
														if current_time < arrival_time[i]:
																					lowerCamelCase__      :			Union[str, Any] 						= arrival_time[i]

														lowerCamelCase__      :			Any 						= 0
														# Index showing the location of the process being performed
														lowerCamelCase__      :			Union[str, Any] 						= 0
														# Saves the current response ratio.
														lowerCamelCase__      :			Any 						= 0
														for i in range(0       ,    UpperCamelCase   ):
																					if finished_process[i] == 0 and arrival_time[i] <= current_time:
																												lowerCamelCase__      :			Optional[int] 						= (burst_time[i] + (current_time - arrival_time[i])) / burst_time[
																												    i
																												]
																					if response_ratio < temp:
																												lowerCamelCase__      :			int 						= temp
																												lowerCamelCase__      :			str 						= i

        # Calculate the turn around time
														lowerCamelCase__      :			Optional[int] 						= current_time + burst_time[loc] - arrival_time[loc]
														current_time += burst_time[loc]
														# Indicates that the process has been performed.
														lowerCamelCase__      :			List[str] 						= 1
														# Increase finished_process_count by 1
														finished_process_count += 1

							return turn_around_time





def 				SCREAMING_SNAKE_CASE_ (UpperCamelCase       ,    UpperCamelCase       ,    UpperCamelCase       ,    UpperCamelCase   )   -> list:
							lowerCamelCase__      :			int 						= [0] * no_of_process
							for i in range(0       ,    UpperCamelCase   ):
														lowerCamelCase__      :			Optional[Any] 						= turn_around_time[i] - burst_time[i]
							return waiting_time


if __name__ == "__main__":
			_A			:    List[str]					  =5
			_A			:    Optional[Any]					  =['''A''', '''B''', '''C''', '''D''', '''E''']
			_A			:    Optional[int]					  =[1, 2, 3, 4, 5]
			_A			:    Dict					  =[1, 2, 3, 4, 5]

			_A			:    Any					  =calculate_turn_around_time(
			    process_name, arrival_time, burst_time, no_of_process
			)
			_A			:    Optional[int]					  =calculate_waiting_time(
			    process_name, turn_around_time, burst_time, no_of_process
			)

			print('''Process name \tArrival time \tBurst time \tTurn around time \tWaiting time''')
			for i in range(0, no_of_process):
						print(
						    F'{process_name[i]}\t\t{arrival_time[i]}\t\t{burst_time[i]}\t\t'
						    F'{turn_around_time[i]}\t\t\t{waiting_time[i]}'
						)

			print(F'average waiting time : {mean(waiting_time):.5f}')
			print(F'average turn around time : {mean(turn_around_time):.5f}')

