





from __future__ import annotations

_snake_case  :   str						   =  tuple[int, int, int]
_snake_case  :   List[str]						   =  tuple[str, str, str]


# used alphabet --------------------------
# from string.ascii_uppercase
_snake_case  :   Union[str, Any]						   =  'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

# -------------------------- default selection --------------------------
# rotors --------------------------
_snake_case  :   Any						   =  'EGZWVONAHDCLFQMSIPJBYUKXTR'
_snake_case  :   Any						   =  'FOBHMDKEXQNRAULPGSJVTYICZW'
_snake_case  :   Dict						   =  'ZJXESIUQLHAVRMDOYGTNFWPBKC'
# reflector --------------------------
_snake_case  :   Union[str, 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 --------------------------
_snake_case  :   Dict						   =  'RMDJXFUWGISLHVTCQNKYPBEZOA'
_snake_case  :   str						   =  'SGLCPQWZHKXAREONTFBVIYJUDM'
_snake_case  :   List[Any]						   =  'HVSICLTYKQUBXDWAJZOMFGPREN'
_snake_case  :   int						   =  'RZWQHFMVDBKICJLNTUXAGYPSOE'
_snake_case  :   str						   =  'LFKIJODBEGAMQPXVUHYSTCZRWN'
_snake_case  :   Optional[int]						   =  'KOAEGVDHXPQZMLFTYWJNBRCIUS'

def   a_   (			lowerCAmelCase_				:      RotorPositionT,     lowerCAmelCase_				:      RotorSelectionT,     lowerCAmelCase_				:      str     ):
   # Checks if there are 3 unique rotors

   if (unique_rotsel := len(set(lowerCAmelCase_     )     )) < 3:
      __lowerCAmelCase							     =     F"""Please use 3 unique rotors (not {unique_rotsel})"""
      raise Exception(lowerCAmelCase_     )

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

   # Validates string and returns dict
   __lowerCAmelCase							     =     _plugboard(lowerCAmelCase_     )

   return rotpos, rotsel, pbdict

def   a_   (			lowerCAmelCase_				:      str     ):

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

   pbstring.replace(' ',     ''     )

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

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

   return pb

def   a_   (			lowerCAmelCase_				:      str,     lowerCAmelCase_				:      RotorPositionT,     lowerCAmelCase_				:      RotorSelectionT = (rotora, rotora, rotora),     lowerCAmelCase_				:      str = "",     ):
   __lowerCAmelCase							     =     text.upper()
   __lowerCAmelCase     ,     __lowerCAmelCase     ,     __lowerCAmelCase							     =     _validator(
       lowerCAmelCase_,     lowerCAmelCase_,     plugb.upper()     )

   __lowerCAmelCase     ,     __lowerCAmelCase     ,     __lowerCAmelCase							     =     rotor_position
   __lowerCAmelCase     ,     __lowerCAmelCase     ,     __lowerCAmelCase							     =     rotor_selection
   rotorposa -= 1
   rotorposa -= 1
   rotorposa -= 1

   __lowerCAmelCase							     =     []

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

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

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

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

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

         __lowerCAmelCase							     =     reflector[symbol]

         # 2nd rotors
         __lowerCAmelCase							     =     abc[rotora.index(lowerCAmelCase_     ) - rotorposa]
         __lowerCAmelCase							     =     abc[rotora.index(lowerCAmelCase_     ) - rotorposa]
         __lowerCAmelCase							     =     abc[rotora.index(lowerCAmelCase_     ) - rotorposa]

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

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

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

   return "".join(lowerCAmelCase_     )


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

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








_snake_case  :   List[str]						   =  {
    'meter': 'm',
    'kilometer': 'km',
    'megametre': 'Mm',
    'gigametre': 'Gm',
    'terametre': 'Tm',
    'petametre': 'Pm',
    'exametre': 'Em',
    'zettametre': 'Zm',
    'yottametre': 'Ym',
}
# Exponent of the factor(meter)
_snake_case  :   List[Any]						   =  {
    'm': 0,
    'km': 3,
    'Mm': 6,
    'Gm': 9,
    'Tm': 12,
    'Pm': 15,
    'Em': 18,
    'Zm': 21,
    'Ym': 24,
}

def   a_   (			lowerCAmelCase_				:      float,     lowerCAmelCase_				:      str,     lowerCAmelCase_				:      str     ):
   __lowerCAmelCase							     =     from_type.lower().strip('s'     )
   __lowerCAmelCase							     =     to_type.lower().strip('s'     )

   __lowerCAmelCase							     =     UNIT_SYMBOL.get(lowerCAmelCase_,     lowerCAmelCase_     )
   __lowerCAmelCase							     =     UNIT_SYMBOL.get(lowerCAmelCase_,     lowerCAmelCase_     )

   if from_sanitized not in METRIC_CONVERSION:
      __lowerCAmelCase							     =     (
          F"""Invalid 'from_type' value: {from_type!r}.\n"""
          F"""Conversion abbreviations are: {", ".join(lowerCAmelCase_     )}"""
      )
      raise ValueError(lowerCAmelCase_     )
   if to_sanitized not in METRIC_CONVERSION:
      __lowerCAmelCase							     =     (
          F"""Invalid 'to_type' value: {to_type!r}.\n"""
          F"""Conversion abbreviations are: {", ".join(lowerCAmelCase_     )}"""
      )
      raise ValueError(lowerCAmelCase_     )
   __lowerCAmelCase							     =     METRIC_CONVERSION[from_sanitized]
   __lowerCAmelCase							     =     METRIC_CONVERSION[to_sanitized]
   __lowerCAmelCase							     =     1

   if from_exponent > to_exponent:
      __lowerCAmelCase							     =     from_exponent - to_exponent
   else:
      __lowerCAmelCase							     =     -(to_exponent - from_exponent)

   return value * pow(10,     lowerCAmelCase_     )


if __name__ == "__main__":
     from doctest import testmod

     testmod()

