

import os
import random
import sys

from . import cryptomath_module as cryptomath
from . import rabin_miller

lowerCAmelCase     :   List[str]						     =  3

def    A_  (							a  ):

      """simple docstring"""



      print('Generating primitive root of p'  )
      while True:
            SCREAMING_SNAKE_CASE_				:  Optional[Any]           =     random.randrange(3					,   a  )
            if pow(a					,   2					,   a  ) == 1:
                  continue
            if pow(a					,   a					,   a  ) == 1:
                  continue
            return g

def    A_  (							a  ):

      """simple docstring"""



      print('Generating prime p...'  )
      SCREAMING_SNAKE_CASE_				:  Optional[int]           =     rabin_miller.generate_large_prime(a  )  # select large prime number.
      SCREAMING_SNAKE_CASE_				:  Dict           =     primitive_root(a  )  # one primitive root on modulo p.
      SCREAMING_SNAKE_CASE_				:  int           =     random.randrange(3					,   a  )  # private_key -> have to be greater than 2 for safety.
      SCREAMING_SNAKE_CASE_				:  Dict           =     cryptomath.find_mod_inverse(pow(a					,   a					,   a  )					,   a  )

      SCREAMING_SNAKE_CASE_				:  Tuple           =     (key_size, e_a, e_a, p)
      SCREAMING_SNAKE_CASE_				:  Optional[Any]           =     (key_size, d)

      return public_key, private_key

def    A_  (							a					,   a  ):

      """simple docstring"""



      if os.path.exists(f"{name}_pubkey.txt"  ) or os.path.exists(f"{name}_privkey.txt"  ):
            print('\nWARNING:'  )
            print(
                f"\"{name}_pubkey.txt\" or \"{name}_privkey.txt\" already exists. \n"
                'Use a different name or delete these files and re-run this program.'  )
            sys.exit()

      SCREAMING_SNAKE_CASE_       ,						SCREAMING_SNAKE_CASE_				:  Optional[int]           =     generate_key(a  )
      print(f"\nWriting public key to file {name}_pubkey.txt..."  )
      with open(f"{name}_pubkey.txt"					,   'w'  ) as fo:
            fo.write(f"{public_key[0]},{public_key[1]},{public_key[2]},{public_key[3]}"  )

      print(f"Writing private key to file {name}_privkey.txt..."  )
      with open(f"{name}_privkey.txt"					,   'w'  ) as fo:
            fo.write(f"{private_key[0]},{private_key[1]}"  )

def    A_  (							):

      """simple docstring"""



      print('Making key files...'  )
      make_key_files('elgamal'					,   2_0_4_8  )
      print('Key files generation successful'  )


if __name__ == "__main__":
    main()









def    A_  (							a  ):

      """simple docstring"""



      if upper_limit < 0:
            raise ValueError('Limit for the Catalan sequence must be ≥ 0'  )

      SCREAMING_SNAKE_CASE_				:  List[str]           =     [0] * (upper_limit + 1)

      # Base case: C(0) = C(1) = 1
      SCREAMING_SNAKE_CASE_				:  Any           =     1
      if upper_limit > 0:
            SCREAMING_SNAKE_CASE_				:  int           =     1

      # Recurrence relation: C(i) = sum(C(j).C(i-j-1)), from j = 0 to i
      for i in range(2					,   upper_limit + 1  ):
            for j in range(a  ):
                  catalan_list[i] += catalan_list[j] * catalan_list[i - j - 1]

      return catalan_list


if __name__ == "__main__":
    print('\n********* Catalan Numbers Using Dynamic Programming ************\n')
    print('\n*** Enter -1 at any time to quit ***')
    print('\nEnter the upper limit (≥ 0) for the Catalan number sequence: ', end='')
    try:
        while True:
            lowerCAmelCase     :   Union[str, Any]						     =  int(input().strip())
            if N < 0:
                print('\n********* Goodbye!! ************')
                break
            else:
                print(F'The Catalan numbers from 0 through {N} are:')
                print(catalan_numbers(N))
                print('Try another upper limit for the sequence: ', end='')
    except (NameError, ValueError):
        print('\n********* Invalid input, goodbye! ************\n')

    import doctest

    doctest.testmod()






