



'''simple docstring'''





import string

import numpy




def 							lowerCamelCase	(					_snake_case	:    int  ,_snake_case	:    int							):





    '''simple docstring'''


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


class 					snake_case			:
       lowerCAmelCase__	: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)
       lowerCAmelCase__	:Dict     =       numpy.vectorize(lambda UpperCamelCase : x % 36 )

       lowerCAmelCase__	:Union[str, Any]     =       numpy.vectorize(UpperCamelCase )



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



       def 				_a   (					self  ,UpperCAmelCase_   )	->				int:
           return self.key_string.index(UpperCAmelCase_   )



       def 				_a   (					self  ,UpperCAmelCase_   )	->				str:
           return self.key_string[round(UpperCAmelCase_   )]



       def 				_a   (					self   )	->				None:
           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(UpperCAmelCase_  ,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(UpperCAmelCase_   )



       def 				_a   (					self  ,UpperCAmelCase_   )	->				str:
           lowercase__									=    [char for char in text.upper() if char in self.key_string]

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

           return "".join(UpperCAmelCase_   )



       def 				_a   (					self  ,UpperCAmelCase_   )	->				str:
           lowercase__									=    self.process_text(text.upper()   )
           lowercase__									=    ""

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

           return encrypted



       def 				_a   (					self   )	->				numpy.ndarray:
           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(UpperCAmelCase_   )   )







       def 				_a   (					self  ,UpperCAmelCase_   )	->				str:
           lowercase__									=    self.make_decrypt_key()
           lowercase__									=    self.process_text(text.upper()   )
           lowercase__									=    ""

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

           return decrypted





def 							lowerCamelCase	(					):





    '''simple docstring'''


    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(_snake_case							):
        lowercase__									=    [int(_snake_case							) for x in input().split()]
        hill_matrix.append(_snake_case							)

    lowercase__									=    HillCipher(numpy.array(_snake_case							)							)

    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(_snake_case							)							)
    elif option == "2":
        lowercase__									=    input("What text would you like to decrypt?: "							)
        print("Your decrypted text is:"							)
        print(hc.decrypt(_snake_case							)							)


if __name__ == "__main__":
 import doctest

 doctest.testmod()

 main()









'''simple docstring'''





from __future__ import annotations

import time

import numpy as np

SCREAMING_SNAKE_CASE__          =  [8, 5, 9, 7]
SCREAMING_SNAKE_CASE__          =  [
    [2, 0, 1, 1],
    [0, 1, 2, 1],
    [4, 0, 0, 3],
    [0, 2, 1, 0],
    [1, 0, 3, 0],
]
SCREAMING_SNAKE_CASE__          =  [
    [3, 2, 1, 4],
    [0, 2, 5, 2],
    [5, 1, 0, 5],
    [1, 5, 3, 0],
    [3, 0, 3, 3],
]


class 					snake_case			:



       def __init__(					self  ,UpperCAmelCase_  ,UpperCAmelCase_  ,UpperCAmelCase_  ,)	->				None:
           lowercase__									=    claim_vector
           lowercase__									=    allocated_resources_table
           lowercase__									=    maximum_claim_table



       def 				_a   (					self   )	->				list[int]:
           return [
               sum(p_item[i] for p_item in self.__allocated_resources_table   )
               for i in range(len(self.__allocated_resources_table[0]   )   )
           ]



       def 				_a   (					self   )	->				list[int]:
           return np.array(self.__claim_vector   ) - np.array(
               self.__processes_resource_summation()   )



       def 				_a   (					self   )	->				list[list[int]]:
           return [
               list(np.array(self.__maximum_claim_table[i]   ) - np.array(UpperCAmelCase_   )   )
               for i, allocated_resource in enumerate(self.__allocated_resources_table   )
           ]



       def 				_a   (					self   )	->				dict[int, list[int]]:
           return {self.__need().index(UpperCAmelCase_   ): i for i in self.__need()}



       def 				_a   (					self  ,**UpperCAmelCase_   )	->				None:
           lowercase__									=    self.__need()
           lowercase__									=    self.__allocated_resources_table
           lowercase__									=    self.__available_resources()
           lowercase__									=    self.__need_index_manager()
           for kw, val in kwargs.items():
               if kw and val is True:
                   self.__pretty_data()
           print("_" * 50 + "\n"   )
           while need_list:
               lowercase__									=    False
               for each_need in need_list:
                   lowercase__									=    True
                   for index, need in enumerate(UpperCAmelCase_   ):
                       if need > available_resources[index]:
                           lowercase__									=    False
                           break
                   if execution:
                       lowercase__									=    True
                       # get the original index of the process from ind_ctrl db
                       for original_need_index, need_clone in need_index_manager.items():
                           if each_need == need_clone:
                               lowercase__									=    original_need_index
                       print(F'''Process {process_number + 1} is executing.'''   )
                       # remove the process run from stack
                       need_list.remove(UpperCAmelCase_   )
                       # update available/freed resources stack
                       lowercase__									=    np.array(UpperCAmelCase_   ) + np.array(
                           alloc_resources_table[process_number]   )
                       print(
                           "Updated available resource stack for processes: "
                           + " ".join([str(UpperCAmelCase_   ) for x in available_resources]   )   )
                       break
               if safe:
                   print("The process is in a safe state.\n"   )
               else:
                   print("System in unsafe state. Aborting...\n"   )
                   break







       def 				_a   (					self   )	->				List[Any]:
           print(" " * 9 + "Allocated Resource Table"   )
           for item in self.__allocated_resources_table:
               print(
                   F'''P{self.__allocated_resources_table.index(UpperCAmelCase_   ) + 1}'''
                   + " ".join(F'''{it:>8}''' for it in item   )
                   + "\n"   )
           print(" " * 9 + "System Resource Table"   )
           for item in self.__maximum_claim_table:
               print(
                   F'''P{self.__maximum_claim_table.index(UpperCAmelCase_   ) + 1}'''
                   + " ".join(F'''{it:>8}''' for it in item   )
                   + "\n"   )
           print(
               "Current Usage by Active Processes: "
               + " ".join(str(UpperCAmelCase_   ) for x in self.__claim_vector   )   )
           print(
               "Initial Available Resources:       "
               + " ".join(str(UpperCAmelCase_   ) for x in self.__available_resources()   )   )
           time.sleep(1   )


if __name__ == "__main__":
 import doctest

 doctest.testmod()




