






'''simple docstring'''



from __future__ import annotations

__UpperCamelCase      :       List[Any]      			=      tuple[int, int, int]
__UpperCamelCase      :       Union[str, Any]      			=      tuple[str, str, str]


# used alphabet --------------------------
# from string.ascii_uppercase
__UpperCamelCase      :       str      			=      """ABCDEFGHIJKLMNOPQRSTUVWXYZ"""

# -------------------------- default selection --------------------------
# rotors --------------------------
__UpperCamelCase      :       List[Any]      			=      """EGZWVONAHDCLFQMSIPJBYUKXTR"""
__UpperCamelCase      :       List[str]      			=      """FOBHMDKEXQNRAULPGSJVTYICZW"""
__UpperCamelCase      :       int      			=      """ZJXESIUQLHAVRMDOYGTNFWPBKC"""
# reflector --------------------------
__UpperCamelCase      :       List[Any]      			=      {
    """A""": """N""",
    """N""": """A""",
    """B""": """O""",
    """O""": """B""",
    """C""": """P""",
    """P""": """C""",
    """D""": """Q""",
    """Q""": """D""",
    """E""": """R""",
    """R""": """E""",
    """F""": """S""",
    """S""": """F""",
    """G""": """T""",
    """T""": """G""",
    """H""": """U""",
    """U""": """H""",
    """I""": """V""",
    """V""": """I""",
    """J""": """W""",
    """W""": """J""",
    """K""": """X""",
    """X""": """K""",
    """L""": """Y""",
    """Y""": """L""",
    """M""": """Z""",
    """Z""": """M""",
}

# -------------------------- extra rotors --------------------------
__UpperCamelCase      :       Tuple      			=      """RMDJXFUWGISLHVTCQNKYPBEZOA"""
__UpperCamelCase      :       Dict      			=      """SGLCPQWZHKXAREONTFBVIYJUDM"""
__UpperCamelCase      :       Optional[Any]      			=      """HVSICLTYKQUBXDWAJZOMFGPREN"""
__UpperCamelCase      :       List[str]      			=      """RZWQHFMVDBKICJLNTUXAGYPSOE"""
__UpperCamelCase      :       List[str]      			=      """LFKIJODBEGAMQPXVUHYSTCZRWN"""
__UpperCamelCase      :       Dict      			=      """KOAEGVDHXPQZMLFTYWJNBRCIUS"""



def    __UpperCAmelCase	(				SCREAMING_SNAKE_CASE__:	RotorPositionT,					SCREAMING_SNAKE_CASE__:	RotorSelectionT,					SCREAMING_SNAKE_CASE__:	str    )  ->			tuple[RotorPositionT, RotorSelectionT, dict[str, str]]:

   """simple docstring"""
   # Checks if there are 3 unique rotors

   if (unique_rotsel := len(set(SCREAMING_SNAKE_CASE__    )    )) < 3:
      __a				     =    f"""Please use 3 unique rotors (not {unique_rotsel})"""
      raise Exception(SCREAMING_SNAKE_CASE__    )

   # Checks if rotor positions are valid
   __a     ,			__a     ,			__a				     =    rotpos
   if not 0 < rotorposa <= len(SCREAMING_SNAKE_CASE__    ):
      __a				     =    f"""First rotor position is not within range of 1..26 ({rotorposa}"""
      raise ValueError(SCREAMING_SNAKE_CASE__    )
   if not 0 < rotorposa <= len(SCREAMING_SNAKE_CASE__    ):
      __a				     =    f"""Second rotor position is not within range of 1..26 ({rotorposa})"""
      raise ValueError(SCREAMING_SNAKE_CASE__    )
   if not 0 < rotorposa <= len(SCREAMING_SNAKE_CASE__    ):
      __a				     =    f"""Third rotor position is not within range of 1..26 ({rotorposa})"""
      raise ValueError(SCREAMING_SNAKE_CASE__    )

   # Validates string and returns dict
   __a				     =    _plugboard(SCREAMING_SNAKE_CASE__    )

   return rotpos, rotsel, pbdict



def    __UpperCAmelCase	(				SCREAMING_SNAKE_CASE__:	str    )  ->			dict[str, str]:

   """simple docstring"""

   # tests the input string if it
   # a) is type string
   # b) has even length (so pairs can be made)
   if not isinstance(SCREAMING_SNAKE_CASE__,					SCREAMING_SNAKE_CASE__    ):
      __a				     =    f"""Plugboard setting isn't type string ({type(SCREAMING_SNAKE_CASE__    )})"""
      raise TypeError(SCREAMING_SNAKE_CASE__    )
   elif len(SCREAMING_SNAKE_CASE__    ) % 2 != 0:
      __a				     =    f"""Odd number of symbols ({len(SCREAMING_SNAKE_CASE__    )})"""
      raise Exception(SCREAMING_SNAKE_CASE__    )
   elif pbstring == "":
      return {}

   pbstring.replace(' ',					''    )

   # Checks if all characters are unique
   __a				     =    set()
   for i in pbstring:
      if i not in abc:
         __a				     =    f"""'{i}' not in list of symbols"""
         raise Exception(SCREAMING_SNAKE_CASE__    )
      elif i in tmppbl:
         __a				     =    f"""Duplicate symbol ({i})"""
         raise Exception(SCREAMING_SNAKE_CASE__    )
      else:
         tmppbl.add(SCREAMING_SNAKE_CASE__    )
   del tmppbl

   # Created the dictionary
   __a				     =    {}
   for j in range(0,					len(SCREAMING_SNAKE_CASE__    ) - 1,					2    ):
      __a				     =    pbstring[j + 1]
      __a				     =    pbstring[j]

   return pb



def    __UpperCAmelCase	(				SCREAMING_SNAKE_CASE__:	str,					SCREAMING_SNAKE_CASE__:	RotorPositionT,					SCREAMING_SNAKE_CASE__:	RotorSelectionT = (rotora, rotora, rotora),					SCREAMING_SNAKE_CASE__:	str = "",					)  ->			str:

   """simple docstring"""
   __a				     =    text.upper()
   __a     ,			__a     ,			__a				     =    _validator(
       SCREAMING_SNAKE_CASE__,					SCREAMING_SNAKE_CASE__,					plugb.upper()    )

   __a     ,			__a     ,			__a				     =    rotor_position
   __a     ,			__a     ,			__a				     =    rotor_selection
   rotorposa -= 1
   rotorposa -= 1
   rotorposa -= 1

   __a				     =    []

   # encryption/decryption process --------------------------
   for symbol in text:
      if symbol in abc:
         # 1st plugboard --------------------------
         if symbol in plugboard:
            __a				     =    plugboard[symbol]

         # rotor ra --------------------------
         __a				     =    abc.index(SCREAMING_SNAKE_CASE__    ) + rotorposa
         __a				     =    rotora[index % len(SCREAMING_SNAKE_CASE__    )]

         # rotor rb --------------------------
         __a				     =    abc.index(SCREAMING_SNAKE_CASE__    ) + rotorposa
         __a				     =    rotora[index % len(SCREAMING_SNAKE_CASE__    )]

         # rotor rc --------------------------
         __a				     =    abc.index(SCREAMING_SNAKE_CASE__    ) + rotorposa
         __a				     =    rotora[index % len(SCREAMING_SNAKE_CASE__    )]

         # reflector --------------------------
         # this is the reason you don't need another machine to decipher

         __a				     =    reflector[symbol]

         # 2nd rotors
         __a				     =    abc[rotora.index(SCREAMING_SNAKE_CASE__    ) - rotorposa]
         __a				     =    abc[rotora.index(SCREAMING_SNAKE_CASE__    ) - rotorposa]
         __a				     =    abc[rotora.index(SCREAMING_SNAKE_CASE__    ) - rotorposa]

         # 2nd plugboard
         if symbol in plugboard:
            __a				     =    plugboard[symbol]

         # moves/resets rotor positions
         rotorposa += 1
         if rotorposa >= len(SCREAMING_SNAKE_CASE__    ):
            __a				     =    0
            rotorposa += 1
         if rotorposa >= len(SCREAMING_SNAKE_CASE__    ):
            __a				     =    0
            rotorposa += 1
         if rotorposa >= len(SCREAMING_SNAKE_CASE__    ):
            __a				     =    0

        # else:
        #    pass
        #    Error could be also raised
        #    raise ValueError(
        #       'Invalid symbol('+repr(symbol)+')')
      result.append(SCREAMING_SNAKE_CASE__    )

   return "".join(SCREAMING_SNAKE_CASE__    )


if __name__ == "__main__":
 __UpperCamelCase      :       str      			=      """This is my Python script that emulates the Enigma machine from WWII."""
 __UpperCamelCase      :       int      			=      (1, 1, 1)
 __UpperCamelCase      :       Optional[Any]      			=      """pictures"""
 __UpperCamelCase      :       Any      			=      (rotora, rotora, rotora)
 __UpperCamelCase      :       Optional[Any]      			=      enigma(message, rotor_pos, rotor_sel, pb)

 print("""Encrypted message:""", en)
 print("""Decrypted message:""", enigma(en, rotor_pos, rotor_sel, pb))







'''simple docstring'''



def    __UpperCAmelCase	(				SCREAMING_SNAKE_CASE__:	int,					SCREAMING_SNAKE_CASE__:	bool = False    )  ->			bool:

   """simple docstring"""
   if n == 2:
      return True
   if not n % 2 or n < 2:
      return False
   if n > 5 and n % 10 not in (1, 3, 7, 9):  # can quickly check last digit
      return False
   if n > 3317044064679887385961981 and not allow_probable:
      raise ValueError(
          'Warning: upper bound of deterministic test is exceeded. '
          'Pass allow_probable=True to allow probabilistic test. '
          'A return value of True indicates a probable prime.'    )
   # array bounds provided by analysis
   __a				     =    [
       2047,
       1373653,
       25326001,
       3215031751,
       2152302898747,
       3474749660383,
       341550071728321,
       1,
       3825123056546413051,
       1,
       1,
       318665857834031151167461,
       3317044064679887385961981,
   ]

   __a				     =    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
   for idx, _p in enumerate(SCREAMING_SNAKE_CASE__,					1    ):
      if n < _p:
         # then we have our last prime to check
         __a				     =    primes[:idx]
         break
   __a     ,			__a				     =    n - 1, 0
   # break up n -1 into a power of 2 (s) and
   # remaining odd component
   # essentially, solve for d * 2 ** s == n - 1
   while d % 2 == 0:
      d //= 2
      s += 1
   for prime in plist:
      __a				     =    False
      for r in range(SCREAMING_SNAKE_CASE__    ):
         __a				     =    pow(SCREAMING_SNAKE_CASE__,					d * 2**r,					SCREAMING_SNAKE_CASE__    )
         # see article for analysis explanation for m
         if (r == 0 and m == 1) or ((m + 1) % n == 0):
            __a				     =    True
            # this loop will not determine compositeness
            break
      if pr:
         continue
      # if pr is False, then the above loop never evaluated to true,
      # and the n MUST be composite
      return False
   return True



def    __UpperCAmelCase	(				)  ->			None:

   """simple docstring"""
   assert not miller_rabin(561    )
   assert miller_rabin(563    )
   # 2047

   assert not miller_rabin(838201    )
   assert miller_rabin(838207    )
   # 1_373_653

   assert not miller_rabin(17316001    )
   assert miller_rabin(17316017    )
   # 25_326_001

   assert not miller_rabin(3078386641    )
   assert miller_rabin(3078386653    )
   # 3_215_031_751

   assert not miller_rabin(1713045574801    )
   assert miller_rabin(1713045574819    )
   # 2_152_302_898_747

   assert not miller_rabin(2779799728307    )
   assert miller_rabin(2779799728327    )
   # 3_474_749_660_383

   assert not miller_rabin(113850023909441    )
   assert miller_rabin(113850023909527    )
   # 341_550_071_728_321

   assert not miller_rabin(1275041018848804351    )
   assert miller_rabin(1275041018848804391    )
   # 3_825_123_056_546_413_051

   assert not miller_rabin(79666464458507787791867    )
   assert miller_rabin(79666464458507787791951    )
   # 318_665_857_834_031_151_167_461

   assert not miller_rabin(552840677446647897660333    )
   assert miller_rabin(552840677446647897660359    )
   # 3_317_044_064_679_887_385_961_981
   # upper limit for probabilistic test


if __name__ == "__main__":
 test_miller_rabin()