



from __future__ import annotations

__snake_case     :Union[str, Any]			       =tuple[int, int, int]
__snake_case     :Tuple			       =tuple[str, str, str]


# used alphabet --------------------------
# from string.ascii_uppercase
__snake_case     :Tuple			       ='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

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






def  lowerCamelCase_	(      lowerCAmelCase__	:	RotorPositionT			,	lowerCAmelCase__	:	RotorSelectionT			,	lowerCAmelCase__	:	str				)       ->							tuple[RotorPositionT, RotorSelectionT, dict[str, str]]:

							'''simple docstring'''






							if (unique_rotsel := len(set(lowerCAmelCase__				)				)) < 3:
														A      						=    F'''Please use 3 unique rotors (not {unique_rotsel})'''
														raise Exception(lowerCAmelCase__				)

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

							# Validates string and returns dict
							A      						=    _plugboard(lowerCAmelCase__				)

							return rotpos, rotsel, pbdict






def  lowerCamelCase_	(      lowerCAmelCase__	:	str				)       ->							dict[str, str]:

							'''simple docstring'''






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

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

							return pb






def  lowerCamelCase_	(      lowerCAmelCase__	:	str			,	lowerCAmelCase__	:	RotorPositionT			,	lowerCAmelCase__	:	RotorSelectionT = (rotora, rotora, rotora)			,	lowerCAmelCase__	:	str = ""			,	)       ->							str:

							'''simple docstring'''






							A      						=    text.upper()
							A						,   A						,   A      						=    _validator(
							    lowerCAmelCase__			,	lowerCAmelCase__			,	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(lowerCAmelCase__				) + rotorposa
																					A      						=    rotora[index % len(lowerCAmelCase__				)]

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

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

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

																					A      						=    reflector[symbol]

																					# 2nd rotors
																					A      						=    abc[rotora.index(lowerCAmelCase__				) - rotorposa]
																					A      						=    abc[rotora.index(lowerCAmelCase__				) - rotorposa]
																					A      						=    abc[rotora.index(lowerCAmelCase__				) - rotorposa]

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

																					# moves/resets rotor positions
																					rotorposa += 1
																					if rotorposa >= len(lowerCAmelCase__				):
																												A      						=    0
																												rotorposa += 1
																					if rotorposa >= len(lowerCAmelCase__				):
																												A      						=    0
																												rotorposa += 1
																					if rotorposa >= len(lowerCAmelCase__				):
																												A      						=    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     :Optional[Any]			       ='This is my Python script that emulates the Enigma machine from WWII.'
				__snake_case     :Any			       =(1, 1, 1)
				__snake_case     :Optional[int]			       ='pictures'
				__snake_case     :Dict			       =(rotora, rotora, rotora)
				__snake_case     :Union[str, Any]			       =enigma(message, rotor_pos, rotor_sel, pb)

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






'''simple docstring'''


import re
import string

import numpy as np

import datasets


_SCREAMING_SNAKE_CASE									=				"\nReturns the rate at which the input predicted strings exactly match their references, ignoring any strings input as part of the regexes_to_ignore list.\n"

_SCREAMING_SNAKE_CASE									=				"\nArgs:\n    predictions: List of predicted texts.\n    references: List of reference texts.\n    regexes_to_ignore: List, defaults to None. Regex expressions of characters to\n        ignore when calculating the exact matches. Note: these regexes are removed\n        from the input data before the changes based on the options below (e.g. ignore_case,\n        ignore_punctuation, ignore_numbers) are applied.\n    ignore_case: Boolean, defaults to False. If true, turns everything\n        to lowercase so that capitalization differences are ignored.\n    ignore_punctuation: Boolean, defaults to False. If true, removes all punctuation before\n        comparing predictions and references.\n    ignore_numbers: Boolean, defaults to False. If true, removes all punctuation before\n        comparing predictions and references.\nReturns:\n    exact_match: Dictionary containing exact_match rate. Possible values are between 0.0 and 100.0, inclusive.\nExamples:\n    >>> exact_match = datasets.load_metric(\"exact_match\")\n    >>> refs = [\"the cat\", \"theater\", \"YELLING\", \"agent007\"]\n    >>> preds = [\"cat?\", \"theater\", \"yelling\", \"agent\"]\n    >>> results = exact_match.compute(references=refs, predictions=preds)\n    >>> print(round(results[\"exact_match\"], 1))\n    25.0\n\n    >>> exact_match = datasets.load_metric(\"exact_match\")\n    >>> refs = [\"the cat\", \"theater\", \"YELLING\", \"agent007\"]\n    >>> preds = [\"cat?\", \"theater\", \"yelling\", \"agent\"]\n    >>> results = exact_match.compute(references=refs, predictions=preds, regexes_to_ignore=[\"the \", \"yell\"], ignore_case=True, ignore_punctuation=True)\n    >>> print(round(results[\"exact_match\"], 1))\n    50.0\n\n\n    >>> exact_match = datasets.load_metric(\"exact_match\")\n    >>> refs = [\"the cat\", \"theater\", \"YELLING\", \"agent007\"]\n    >>> preds = [\"cat?\", \"theater\", \"yelling\", \"agent\"]\n    >>> results = exact_match.compute(references=refs, predictions=preds, regexes_to_ignore=[\"the \", \"yell\", \"YELL\"], ignore_case=True, ignore_punctuation=True)\n    >>> print(round(results[\"exact_match\"], 1))\n    75.0\n\n    >>> exact_match = datasets.load_metric(\"exact_match\")\n    >>> refs = [\"the cat\", \"theater\", \"YELLING\", \"agent007\"]\n    >>> preds = [\"cat?\", \"theater\", \"yelling\", \"agent\"]\n    >>> results = exact_match.compute(references=refs, predictions=preds, regexes_to_ignore=[\"the \", \"yell\", \"YELL\"], ignore_case=True, ignore_punctuation=True, ignore_numbers=True)\n    >>> print(round(results[\"exact_match\"], 1))\n    100.0\n\n    >>> exact_match = datasets.load_metric(\"exact_match\")\n    >>> refs = [\"The cat sat on the mat.\", \"Theaters are great.\", \"It's like comparing oranges and apples.\"]\n    >>> preds = [\"The cat sat on the mat?\", \"Theaters are great.\", \"It's like comparing apples and oranges.\"]\n    >>> results = exact_match.compute(references=refs, predictions=preds)\n    >>> print(round(results[\"exact_match\"], 1))\n    33.3\n\n"

_SCREAMING_SNAKE_CASE									=				"\n"

@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION    ,_KWARGS_DESCRIPTION		)
class  lowerCAmelCase_		(		datasets.Metric		):




 def 				_snake_case (						self		)     ->				List[str]:
     return datasets.MetricInfo(
         description=_DESCRIPTION      ,  citation=_CITATION      ,  inputs_description=_KWARGS_DESCRIPTION      ,  features=datasets.Features(
             {
                 "predictions": datasets.Value("string"      ,  id="sequence"		),
                 "references": datasets.Value("string"      ,  id="sequence"		),
             }		)      ,  reference_urls=[]      ,  )





 def 				_snake_case (						self      ,  _lowerCAmelCase      ,  _lowerCAmelCase      ,  _lowerCAmelCase=None      ,  _lowerCAmelCase=False      ,  _lowerCAmelCase=False      ,  _lowerCAmelCase=False      ,  )     ->				str:
     if regexes_to_ignore is not None:
         for s in regexes_to_ignore:
             _lowerCAmelCase						      =   np.array([re.sub(_lowerCAmelCase      ,  ""      ,  _lowerCAmelCase		) for x in predictions]		)
             _lowerCAmelCase						      =   np.array([re.sub(_lowerCAmelCase      ,  ""      ,  _lowerCAmelCase		) for x in references]		)
     else:
         _lowerCAmelCase						      =   np.asarray(_lowerCAmelCase		)
         _lowerCAmelCase						      =   np.asarray(_lowerCAmelCase		)

     if ignore_case:
         _lowerCAmelCase						      =   np.char.lower(_lowerCAmelCase		)
         _lowerCAmelCase						      =   np.char.lower(_lowerCAmelCase		)

     if ignore_punctuation:
         _lowerCAmelCase						      =   string.punctuation.maketrans(""      ,  ""      ,  string.punctuation		)
         _lowerCAmelCase						      =   np.char.translate(_lowerCAmelCase      ,  table=_lowerCAmelCase		)
         _lowerCAmelCase						      =   np.char.translate(_lowerCAmelCase      ,  table=_lowerCAmelCase		)

     if ignore_numbers:
         _lowerCAmelCase						      =   string.digits.maketrans(""      ,  ""      ,  string.digits		)
         _lowerCAmelCase						      =   np.char.translate(_lowerCAmelCase      ,  table=_lowerCAmelCase		)
         _lowerCAmelCase						      =   np.char.translate(_lowerCAmelCase      ,  table=_lowerCAmelCase		)

     _lowerCAmelCase						      =   predictions == references

     return {"exact_match": np.mean(_lowerCAmelCase		) * 100}


