





from __future__ import annotations

UpperCAmelCase__						:			Any									=tuple[int, int, int]
UpperCAmelCase__						:			Optional[int]									=tuple[str, str, str]


# used alphabet --------------------------
# from string.ascii_uppercase
UpperCAmelCase__						:			Any									='''ABCDEFGHIJKLMNOPQRSTUVWXYZ'''

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





def      _lowercase					(						_UpperCAmelCase			,      _UpperCAmelCase			,      _UpperCAmelCase				)						->  Tuple:






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

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

	# Validates string and returns dict
	lowerCamelCase	 =_plugboard(_snake_case				)

	return rotpos, rotsel, pbdict





def      _lowercase					(						_UpperCAmelCase				)						->  Tuple:






	if not isinstance(_snake_case			,      _snake_case				):
		lowerCamelCase	 =F"""Plugboard setting isn\'t type string ({type(_snake_case				)})"""
		raise TypeError(_snake_case				)
	elif len(_snake_case				) % 2 != 0:
		lowerCamelCase	 =F"""Odd number of symbols ({len(_snake_case				)})"""
		raise Exception(_snake_case				)
	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(_snake_case				)
		elif i in tmppbl:
			lowerCamelCase	 =F"""Duplicate symbol ({i})"""
			raise Exception(_snake_case				)
		else:
			tmppbl.add(_snake_case				)
	del tmppbl

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

	return pb





def      _lowercase					(						_UpperCAmelCase			,      _UpperCAmelCase			,      _UpperCAmelCase = (rotora, rotora, rotora)			,      _UpperCAmelCase = ""			,      )						->  Union[str, Any]:
	lowerCamelCase	 =text.upper()
	lowerCamelCase ,  lowerCamelCase ,  lowerCamelCase	 =_validator(
	    _snake_case			,      _snake_case			,      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(_snake_case				) + rotorposa
			lowerCamelCase	 =rotora[index % len(_snake_case				)]

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

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

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

			lowerCamelCase	 =reflector[symbol]

			# 2nd rotors
			lowerCamelCase	 =abc[rotora.index(_snake_case				) - rotorposa]
			lowerCamelCase	 =abc[rotora.index(_snake_case				) - rotorposa]
			lowerCamelCase	 =abc[rotora.index(_snake_case				) - rotorposa]

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

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

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

	return "".join(_snake_case				)


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

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












def      _lowercase					(						_UpperCAmelCase			,      _UpperCAmelCase				)						->  list[str]:
				return [sentence[i : i + ngram_size] for i in range(len(_UpperCAmelCase				) - ngram_size + 1				)]


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

							testmod()





