


import json
import os
import re
import unicodedata
from typing import Optional, Tuple

from ...tokenization_utils import PreTrainedTokenizer, _is_control, _is_punctuation, _is_whitespace
from ...utils import logging


SCREAMING_SNAKE_CASE		:List[str]											=       logging.get_logger(__name__)

SCREAMING_SNAKE_CASE		:Dict											=       {
    '''vocab_file''': '''vocab.json''',
    '''merges_file''': '''merges.txt''',
}

SCREAMING_SNAKE_CASE		:Tuple											=       {
    '''vocab_file''': {'''openai-gpt''': '''https://huggingface.co/openai-gpt/resolve/main/vocab.json'''},
    '''merges_file''': {'''openai-gpt''': '''https://huggingface.co/openai-gpt/resolve/main/merges.txt'''},
}

SCREAMING_SNAKE_CASE		:Any											=       {
    '''openai-gpt''': 5_12,
}



def      _lowerCAmelCase  (							lowerCAmelCase_							:Dict							)->Optional[Any]:
   '''simple docstring'''






   snake_case_         =   text.strip()
   if not text:
      return []
   snake_case_         =   text.split()
   return tokens


class       __lowerCAmelCase       (	a   ):






  """simple docstring"""





  def __init__(       self    :    Dict      ,			_lowerCAmelCase    :    Tuple=True      ,			_lowerCAmelCase    :    Any=None      ,			_lowerCAmelCase    :    List[Any]=True      ,			_lowerCAmelCase    :    Optional[int]=None      ,			_lowerCAmelCase    :    Dict=True      ,			)				->	Dict:




     """simple docstring"""
     if never_split is None:
        snake_case_         =   []
     snake_case_         =   do_lower_case
     snake_case_         =   set(_lowerCAmelCase					)
     snake_case_         =   tokenize_chinese_chars
     snake_case_         =   strip_accents
     snake_case_         =   do_split_on_punc



  def    lowerCAmelCase__					(       self    :    Any      ,			_lowerCAmelCase    :    str      ,			_lowerCAmelCase    :    int=None					)				->	List[Any]:




     """simple docstring"""
     snake_case_         =   self.never_split.union(set(_lowerCAmelCase					)					) if never_split else self.never_split
     snake_case_         =   self._clean_text(_lowerCAmelCase					)

     # This was added on November 1st, 2018 for the multilingual and Chinese
     # models. This is also applied to the English models now, but it doesn't
     # matter since the English models were not trained on any Chinese data
     # and generally don't have any Chinese data in them (there are Chinese
     # characters in the vocabulary because Wikipedia does have some Chinese
     # words in the English Wikipedia.).
     if self.tokenize_chinese_chars:
        snake_case_         =   self._tokenize_chinese_chars(_lowerCAmelCase					)
     # prevents treating the same character with different unicode codepoints as different characters
     snake_case_         =   unicodedata.normalize("NFC"      ,			_lowerCAmelCase					)
     snake_case_         =   whitespace_tokenize(_lowerCAmelCase					)
     snake_case_         =   []
     for token in orig_tokens:
        if token not in never_split:
           if self.do_lower_case:
              snake_case_         =   token.lower()
              if self.strip_accents is not False:
                 snake_case_         =   self._run_strip_accents(_lowerCAmelCase					)
           elif self.strip_accents:
              snake_case_         =   self._run_strip_accents(_lowerCAmelCase					)
        split_tokens.extend(self._run_split_on_punc(_lowerCAmelCase      ,			_lowerCAmelCase					)					)

     snake_case_         =   whitespace_tokenize(" ".join(_lowerCAmelCase					)					)
     return output_tokens



  def    lowerCAmelCase__					(       self    :    Tuple      ,			_lowerCAmelCase    :    int					)				->	str:




     """simple docstring"""
     snake_case_         =   unicodedata.normalize("NFD"      ,			_lowerCAmelCase					)
     snake_case_         =   []
     for char in text:
        snake_case_         =   unicodedata.category(_lowerCAmelCase					)
        if cat == "Mn":
           continue
        output.append(_lowerCAmelCase					)
     return "".join(_lowerCAmelCase					)



  def    lowerCAmelCase__					(       self    :    Tuple      ,			_lowerCAmelCase    :    Any      ,			_lowerCAmelCase    :    Optional[Any]=None					)				->	Any:




     """simple docstring"""
     if not self.do_split_on_punc or (never_split is not None and text in never_split):
        return [text]
     snake_case_         =   list(_lowerCAmelCase					)
     snake_case_         =   0
     snake_case_         =   True
     snake_case_         =   []
     while i < len(_lowerCAmelCase					):
        snake_case_         =   chars[i]
        if _is_punctuation(_lowerCAmelCase					):
           output.append([char]					)
           snake_case_         =   True
        else:
           if start_new_word:
              output.append([]					)
           snake_case_         =   False
           output[-1].append(_lowerCAmelCase					)
        i += 1

     return ["".join(_lowerCAmelCase					) for x in output]



  def    lowerCAmelCase__					(       self    :    List[Any]      ,			_lowerCAmelCase    :    Optional[int]					)				->	List[Any]:




     """simple docstring"""
     snake_case_         =   []
     for char in text:
        snake_case_         =   ord(_lowerCAmelCase					)
        if self._is_chinese_char(_lowerCAmelCase					):
           output.append(" "					)
           output.append(_lowerCAmelCase					)
           output.append(" "					)
        else:
           output.append(_lowerCAmelCase					)
     return "".join(_lowerCAmelCase					)



  def    lowerCAmelCase__					(       self    :    Optional[Any]      ,			_lowerCAmelCase    :    str					)				->	Any:




     """simple docstring"""
     # This defines a "chinese character" as anything in the CJK Unicode block:
     #   https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
     #
     # Note that the CJK Unicode block is NOT all Japanese and Korean characters,
     # despite its name. The modern Korean Hangul alphabet is a different block,
     # as is Japanese Hiragana and Katakana. Those alphabets are used to write
     # space-separated words, so they are not treated specially and handled
     # like the all of the other languages.
     if (
         (cp >= 0X4_E_0_0 and cp <= 0X9_F_F_F)
         or (cp >= 0X3_4_0_0 and cp <= 0X4_D_B_F)  #
         or (cp >= 0X2_0_0_0_0 and cp <= 0X2_A_6_D_F)  #
         or (cp >= 0X2_A_7_0_0 and cp <= 0X2_B_7_3_F)  #
         or (cp >= 0X2_B_7_4_0 and cp <= 0X2_B_8_1_F)  #
         or (cp >= 0X2_B_8_2_0 and cp <= 0X2_C_E_A_F)  #
         or (cp >= 0XF_9_0_0 and cp <= 0XF_A_F_F)
         or (cp >= 0X2_F_8_0_0 and cp <= 0X2_F_A_1_F)  #
     ):  #
        return True

     return False



  def    lowerCAmelCase__					(       self    :    List[str]      ,			_lowerCAmelCase    :    int					)				->	Dict:




     """simple docstring"""
     snake_case_         =   []
     for char in text:
        snake_case_         =   ord(_lowerCAmelCase					)
        if cp == 0 or cp == 0XF_F_F_D or _is_control(_lowerCAmelCase					):
           continue
        if _is_whitespace(_lowerCAmelCase					):
           output.append(" "					)
        else:
           output.append(_lowerCAmelCase					)
     return "".join(_lowerCAmelCase					)






def      _lowerCAmelCase  (							lowerCAmelCase_							:int							)->Dict:
   '''simple docstring'''






   snake_case_         =   set()
   snake_case_         =   word[0]
   for char in word[1:]:
      pairs.add((prev_char, char)							)
      snake_case_         =   char
   return pairs



def      _lowerCAmelCase  (							lowerCAmelCase_							:List[Any]							)->Any:
   '''simple docstring'''






   snake_case_         =   text.replace("—"						,  "-"							)
   snake_case_         =   text.replace("–"						,  "-"							)
   snake_case_         =   text.replace("―"						,  "-"							)
   snake_case_         =   text.replace("…"						,  "..."							)
   snake_case_         =   text.replace("´"						,  "'"							)
   snake_case_         =   re.sub(r"(-+|~+|!+|\"+|;+|\?+|\++|,+|\)+|\(+|\\+|\/+|\*+|\[+|\]+|}+|{+|\|+|_+)"						,  r" \1 "						,  lowerCAmelCase_							)
   snake_case_         =   re.sub(r"\s*\n\s*"						,  " \n "						,  lowerCAmelCase_							)
   snake_case_         =   re.sub(r"[^\S\n]+"						,  " "						,  lowerCAmelCase_							)
   return text.strip()



class       __lowerCAmelCase       (	a   ):






  """simple docstring"""





  _SCREAMING_SNAKE_CASE						      =    VOCAB_FILES_NAMES
  _SCREAMING_SNAKE_CASE						      =    PRETRAINED_VOCAB_FILES_MAP
  _SCREAMING_SNAKE_CASE						      =    PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
  _SCREAMING_SNAKE_CASE						      =    ['input_ids', 'attention_mask']



  def __init__(       self    :    int      ,			_lowerCAmelCase    :    Optional[Any]      ,			_lowerCAmelCase    :    List[Any]      ,			_lowerCAmelCase    :    Optional[Any]="<unk>"      ,			**_lowerCAmelCase    :    List[str]					)				->	Dict:




     """simple docstring"""
     super().__init__(unk_token=_lowerCAmelCase      ,			**_lowerCAmelCase					)

     try:
        import ftfy
        from spacy.lang.en import English

        snake_case_         =   English()
        snake_case_         =   _nlp.tokenizer
        snake_case_         =   ftfy.fix_text
     except ImportError:
        logger.warning("ftfy or spacy is not installed using BERT BasicTokenizer instead of SpaCy & ftfy."					)
        snake_case_         =   BasicTokenizer(do_lower_case=_lowerCAmelCase					)
        snake_case_         =   None

     with open(_lowerCAmelCase      ,			encoding="utf-8"					) as vocab_handle:
        snake_case_         =   json.load(_lowerCAmelCase					)
     snake_case_         =   {v: k for k, v in self.encoder.items()}
     with open(_lowerCAmelCase      ,			encoding="utf-8"					) as merges_handle:
        snake_case_         =   merges_handle.read().split("\n"					)[1:-1]
     snake_case_         =   [tuple(merge.split()					) for merge in merges]
     snake_case_         =   dict(zip(_lowerCAmelCase      ,			range(len(_lowerCAmelCase					)					)					)					)
     snake_case_         =   {}



  @property
  def    lowerCAmelCase__					(       self    :    Tuple					)				->	int:




     """simple docstring"""
     return True



  @property
  def    lowerCAmelCase__					(       self    :    List[str]					)				->	Optional[int]:




     """simple docstring"""
     return len(self.encoder					)



  def    lowerCAmelCase__					(       self    :    Tuple					)				->	List[Any]:




     """simple docstring"""
     return dict(self.encoder      ,			**self.added_tokens_encoder					)



  def    lowerCAmelCase__					(       self    :    Union[str, Any]      ,			_lowerCAmelCase    :    Union[str, Any]					)				->	List[str]:




     """simple docstring"""
     snake_case_         =   tuple(token[:-1]					) + (token[-1] + "</w>",)
     if token in self.cache:
        return self.cache[token]
     snake_case_         =   get_pairs(_lowerCAmelCase					)

     if not pairs:
        return token + "</w>"

     while True:
        snake_case_         =   min(_lowerCAmelCase      ,			key=lambda _lowerCAmelCase					: self.bpe_ranks.get(_lowerCAmelCase      ,			float("inf"					)					)					)
        if bigram not in self.bpe_ranks:
           break
        snake_case_      ,      snake_case_         =   bigram
        snake_case_         =   []
        snake_case_         =   0
        while i < len(_lowerCAmelCase					):
           try:
              snake_case_         =   word.index(_lowerCAmelCase      ,			_lowerCAmelCase					)
           except ValueError:
              new_word.extend(word[i:]					)
              break
           else:
              new_word.extend(word[i:j]					)
              snake_case_         =   j

           if word[i] == first and i < len(_lowerCAmelCase					) - 1 and word[i + 1] == second:
              new_word.append(first + second					)
              i += 2
           else:
              new_word.append(word[i]					)
              i += 1
        snake_case_         =   tuple(_lowerCAmelCase					)
        snake_case_         =   new_word
        if len(_lowerCAmelCase					) == 1:
           break
        else:
           snake_case_         =   get_pairs(_lowerCAmelCase					)
     snake_case_         =   " ".join(_lowerCAmelCase					)
     if word == "\n  </w>":
        snake_case_         =   "\n</w>"
     snake_case_         =   word
     return word



  def    lowerCAmelCase__					(       self    :    List[Any]      ,			_lowerCAmelCase    :    Dict					)				->	Dict:




     """simple docstring"""
     snake_case_         =   []
     if self.fix_text is None:
        # Using BERT's BasicTokenizer
        snake_case_         =   self.nlp.tokenize(_lowerCAmelCase					)
        for token in text:
           split_tokens.extend(list(self.bpe(_lowerCAmelCase					).split(" "					)					)					)
     else:
        # Using SpaCy & ftfy (original tokenization process of OpenAI GPT)
        snake_case_         =   self.nlp(text_standardize(self.fix_text(_lowerCAmelCase					)					)					)
        for token in text:
           split_tokens.extend(list(self.bpe(token.text.lower()					).split(" "					)					)					)
     return split_tokens



  def    lowerCAmelCase__					(       self    :    Dict      ,			_lowerCAmelCase    :    List[Any]					)				->	Optional[int]:




     """simple docstring"""
     return self.encoder.get(_lowerCAmelCase      ,			self.encoder.get(self.unk_token					)					)



  def    lowerCAmelCase__					(       self    :    Tuple      ,			_lowerCAmelCase    :    Any					)				->	Optional[int]:




     """simple docstring"""
     return self.decoder.get(_lowerCAmelCase      ,			self.unk_token					)



  def    lowerCAmelCase__					(       self    :    str      ,			_lowerCAmelCase    :    Optional[int]					)				->	List[str]:




     """simple docstring"""
     snake_case_         =   "".join(_lowerCAmelCase					).replace("</w>"      ,			" "					).strip()
     return out_string



  def    lowerCAmelCase__					(       self    :    List[str]      ,			_lowerCAmelCase    :    str      ,			_lowerCAmelCase    :    Optional[str] = None					)				->	Tuple[str]:




     """simple docstring"""
     if not os.path.isdir(_lowerCAmelCase					):
        logger.error(F'''Vocabulary path ({save_directory}) should be a directory'''					)
        return
     snake_case_         =   os.path.join(
         _lowerCAmelCase      ,			(filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"]					)
     snake_case_         =   os.path.join(
         _lowerCAmelCase      ,			(filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["merges_file"]					)

     with open(_lowerCAmelCase      ,			"w"      ,			encoding="utf-8"					) as f:
        f.write(json.dumps(self.encoder      ,			indent=2      ,			sort_keys=_lowerCAmelCase      ,			ensure_ascii=_lowerCAmelCase					) + "\n"					)

     snake_case_         =   0
     with open(_lowerCAmelCase      ,			"w"      ,			encoding="utf-8"					) as writer:
        writer.write("#version: 0.2\n"					)
        for bpe_tokens, token_index in sorted(self.bpe_ranks.items()      ,			key=lambda _lowerCAmelCase					: kv[1]					):
           if index != token_index:
              logger.warning(
                  F'''Saving vocabulary to {merge_file}: BPE merge indices are not consecutive.'''
                  " Please check that the tokenizer is not corrupted!"					)
              snake_case_         =   token_index
           writer.write(" ".join(_lowerCAmelCase					) + "\n"					)
           index += 1

     return vocab_file, merge_file








def      _lowerCAmelCase  (							lowerCAmelCase_							:Dict						,  lowerCAmelCase_							:Optional[int]						,  lowerCAmelCase_							:Tuple							)->Optional[Any]:
   '''simple docstring'''






   assert b != 0, "This cannot accept modulo that is == 0"
   if n == 0:
      return 1

   if n % 2 == 1:
      return (bin_exp_mod(lowerCAmelCase_						,  n - 1						,  lowerCAmelCase_							) * a) % b

   snake_case_         =   bin_exp_mod(lowerCAmelCase_						,  n / 2						,  lowerCAmelCase_							)
   return (r * r) % b


if __name__ == "__main__":
   try:
      SCREAMING_SNAKE_CASE		:str											=       int(input('''Enter Base : ''').strip())
      SCREAMING_SNAKE_CASE		:List[Any]											=       int(input('''Enter Power : ''').strip())
      SCREAMING_SNAKE_CASE		:Dict											=       int(input('''Enter Modulo : ''').strip())
   except ValueError:
      print('''Invalid literal for integer''')

   print(bin_exp_mod(BASE, POWER, MODULO))




