

import os
import unicodedata
from shutil import copyfile
from typing import Any, Dict, List, Optional, Tuple

import sentencepiece as spm

from ...tokenization_utils import AddedToken, PreTrainedTokenizer
from ...utils import SPIECE_UNDERLINE, logging


UpperCAmelCase_							:					Dict		 =   logging.get_logger(__name__)

UpperCAmelCase_							:					Any		 =   {'''vocab_file''': '''spiece.model'''}

UpperCAmelCase_							:					Optional[int]		 =   {
    '''vocab_file''': {
        '''xlnet-base-cased''': '''https://huggingface.co/xlnet-base-cased/resolve/main/spiece.model''',
        '''xlnet-large-cased''': '''https://huggingface.co/xlnet-large-cased/resolve/main/spiece.model''',
    }
}

UpperCAmelCase_							:					List[Any]		 =   {
    '''xlnet-base-cased''': None,
    '''xlnet-large-cased''': None,
}

# Segments (not really needed)
UpperCAmelCase_							:					Tuple		 =   0
UpperCAmelCase_							:					List[str]		 =   1
UpperCAmelCase_							:					Optional[Any]		 =   2
UpperCAmelCase_							:					List[Any]		 =   3
UpperCAmelCase_							:					str		 =   4






class      lowerCamelCase_      (	_lowercase	):
	_lowercase		:   Union[str, Any]     					=				VOCAB_FILES_NAMES
	_lowercase		:   str     					=				PRETRAINED_VOCAB_FILES_MAP
	_lowercase		:   Union[str, Any]     					=				PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
	_lowercase		:   Optional[int]     					=				'''left'''




	def __init__(     self						:     List[str]					,      __A						:     List[Any]					,      __A						:     Optional[int]=False					,      __A						:     str=True					,      __A						:     Optional[Any]=False					,      __A						:     int="<s>"					,      __A						:     str="</s>"					,      __A						:     List[str]="<unk>"					,      __A						:     Any="<sep>"					,      __A						:     Tuple="<pad>"					,      __A						:     Optional[Any]="<cls>"					,      __A						:     Dict="<mask>"					,      __A						:     str=["<eop>", "<eod>"]					,      __A						:     Optional[Dict[str, Any]] = None					,      **__A						:     Any					,      ):
		# Mask token behave like a normal word, i.e. include the space before it
		__A :			Union[str, Any]		    =			AddedToken(__A					,      lstrip=__A					,      rstrip=__A							) if isinstance(__A					,      __A							) else mask_token

		__A :			Optional[int]		    =			{} if sp_model_kwargs is None else sp_model_kwargs

		super().__init__(
		    do_lower_case=__A					,      remove_space=__A					,      keep_accents=__A					,      bos_token=__A					,      eos_token=__A					,      unk_token=__A					,      sep_token=__A					,      pad_token=__A					,      cls_token=__A					,      mask_token=__A					,      additional_special_tokens=__A					,      sp_model_kwargs=self.sp_model_kwargs					,      **__A					,      )

		__A :			int		    =			3

		__A :			List[str]		    =			do_lower_case
		__A :			Optional[Any]		    =			remove_space
		__A :			Any		    =			keep_accents
		__A :			int		    =			vocab_file

		__A :			Union[str, Any]		    =			spm.SentencePieceProcessor(**self.sp_model_kwargs							)
		self.sp_model.Load(__A							)




	@property
	def        lowerCAmelCase_       (     self						:     Union[str, Any]							):
		return len(self.sp_model							)




	def        lowerCAmelCase_       (     self						:     Any							):
		__A :			int		    =			{self.convert_ids_to_tokens(__A							): i for i in range(self.vocab_size							)}
		vocab.update(self.added_tokens_encoder							)
		return vocab




	def __getstate__(     self						:     List[Any]							):
		__A :			Optional[int]		    =			self.__dict__.copy()
		__A :			Dict		    =			None
		return state




	def __setstate__(     self						:     List[str]					,      __A						:     Union[str, Any]							):
		__A :			str		    =			d

		# for backward compatibility
		if not hasattr(self					,      """sp_model_kwargs"""							):
			__A :			List[Any]		    =			{}

		__A :			List[Any]		    =			spm.SentencePieceProcessor(**self.sp_model_kwargs							)
		self.sp_model.Load(self.vocab_file							)




	def        lowerCAmelCase_       (     self						:     Optional[Any]					,      __A						:     List[str]							):
		if self.remove_space:
			__A :			str		    =			""" """.join(inputs.strip().split()							)
		else:
			__A :			Union[str, Any]		    =			inputs
		__A :			Optional[int]		    =			outputs.replace("""``"""					,      """\""""							).replace("""''"""					,      """\""""							)

		if not self.keep_accents:
			__A :			str		    =			unicodedata.normalize("""NFKD"""					,      __A							)
			__A :			Union[str, Any]		    =			"""""".join([c for c in outputs if not unicodedata.combining(__A							)]							)
		if self.do_lower_case:
			__A :			Optional[Any]		    =			outputs.lower()

		return outputs




	def        lowerCAmelCase_       (     self						:     List[str]					,      __A						:     str							):
		__A :			Dict		    =			self.preprocess_text(__A							)
		__A :			str		    =			self.sp_model.encode(__A					,      out_type=__A							)
		__A :			Any		    =			[]
		for piece in pieces:
			if len(__A							) > 1 and piece[-1] == str(""","""							) and piece[-2].isdigit():
				__A :			Dict		    =			self.sp_model.EncodeAsPieces(piece[:-1].replace(__A					,      """"""							)							)
				if piece[0] != SPIECE_UNDERLINE and cur_pieces[0][0] == SPIECE_UNDERLINE:
					if len(cur_pieces[0]							) == 1:
						__A :			List[str]		    =			cur_pieces[1:]
					else:
						__A :			int		    =			cur_pieces[0][1:]
				cur_pieces.append(piece[-1]							)
				new_pieces.extend(__A							)
			else:
				new_pieces.append(__A							)

		return new_pieces




	def        lowerCAmelCase_       (     self						:     str					,      __A						:     int							):
		return self.sp_model.PieceToId(__A							)




	def        lowerCAmelCase_       (     self						:     Optional[Any]					,      __A						:     List[Any]							):
		return self.sp_model.IdToPiece(__A							)




	def        lowerCAmelCase_       (     self						:     Optional[Any]					,      __A						:     List[Any]							):
		__A :			Optional[Any]		    =			"""""".join(__A							).replace(__A					,      """ """							).strip()
		return out_string




	def        lowerCAmelCase_       (     self						:     str					,      __A						:     List[int]					,      __A						:     bool = False					,      __A						:     bool = None					,      __A						:     bool = True					,      **__A						:     Optional[Any]					,      ):
		__A :			Any		    =			kwargs.pop("""use_source_tokenizer"""					,      __A							)

		__A :			str		    =			self.convert_ids_to_tokens(__A					,      skip_special_tokens=__A							)

		# To avoid mixing byte-level and unicode for byte-level BPT
		# we need to build string separately for added tokens and byte-level tokens
		# cf. https://github.com/huggingface/transformers/issues/1133
		__A :			Union[str, Any]		    =			[]
		__A :			Optional[int]		    =			[]
		for token in filtered_tokens:
			if skip_special_tokens and token in self.all_special_ids:
				continue
			if token in self.added_tokens_encoder:
				if current_sub_text:
					sub_texts.append(self.convert_tokens_to_string(__A							)							)
					__A :			Any		    =			[]
				sub_texts.append(__A							)
			else:
				current_sub_text.append(__A							)
		if current_sub_text:
			sub_texts.append(self.convert_tokens_to_string(__A							)							)

		# Mimic the behavior of the Rust tokenizer:
		# By default, there are no spaces between special tokens
		__A :			int		    =			"""""".join(__A							)

		__A :			List[Any]		    =			(
		    clean_up_tokenization_spaces
		    if clean_up_tokenization_spaces is not None
		    else self.clean_up_tokenization_spaces
		)
		if clean_up_tokenization_spaces:
			__A :			int		    =			self.clean_up_tokenization(__A							)
			return clean_text
		else:
			return text




	def        lowerCAmelCase_       (     self						:     Dict					,      __A						:     List[int]					,      __A						:     Optional[List[int]] = None							):
		__A :			Union[str, Any]		    =			[self.sep_token_id]
		__A :			Any		    =			[self.cls_token_id]
		if token_ids_a is None:
			return token_ids_a + sep + cls
		return token_ids_a + sep + token_ids_a + sep + cls




	def        lowerCAmelCase_       (     self						:     Dict					,      __A						:     List[int]					,      __A						:     Optional[List[int]] = None					,      __A						:     bool = False							):

		if already_has_special_tokens:
			return super().get_special_tokens_mask(
			    token_ids_a=__A					,      token_ids_a=__A					,      already_has_special_tokens=__A							)

		if token_ids_a is not None:
			return ([0] * len(__A							)) + [1] + ([0] * len(__A							)) + [1, 1]
		return ([0] * len(__A							)) + [1, 1]




	def        lowerCAmelCase_       (     self						:     List[Any]					,      __A						:     List[int]					,      __A						:     Optional[List[int]] = None							):
		__A :			Dict		    =			[self.sep_token_id]
		__A :			Union[str, Any]		    =			[2]

		if token_ids_a is None:
			return len(token_ids_a + sep							) * [0] + cls_segment_id
		return len(token_ids_a + sep							) * [0] + len(token_ids_a + sep							) * [1] + cls_segment_id




	def        lowerCAmelCase_       (     self						:     Tuple					,      __A						:     str					,      __A						:     Optional[str] = None							):
		if not os.path.isdir(__A							):
			logger.error(F"""Vocabulary path ({save_directory}) should be a directory"""							)
			return
		__A :			Dict		    =			os.path.join(
		    __A					,      (filename_prefix + """-""" if filename_prefix else """""") + VOCAB_FILES_NAMES["""vocab_file"""]							)

		if os.path.abspath(self.vocab_file							) != os.path.abspath(__A							) and os.path.isfile(self.vocab_file							):
			copyfile(self.vocab_file					,      __A							)
		elif not os.path.isfile(self.vocab_file							):
			with open(__A					,      """wb"""							) as fi:
				__A :			List[str]		    =			self.sp_model.serialized_model_proto()
				fi.write(__A							)

		return (out_vocab_file,)








UpperCAmelCase_							:					dict[tuple[int, int, int], int]		 =   {}
def 							__SCREAMING_SNAKE_CASE     (   a__    :   int			,a__    :   int			,a__    :   int       )					->				int:

	# if we are absent twice, or late 3 consecutive days,
	# no further prize strings are possible
	if late == 3 or absent == 2:
		return 0

	# if we have no days left, and have not failed any other rules,
	# we have a prize string
	if days == 0:
		return 1

	# No easy solution, so now we need to do the recursive calculation

	# First, check if the combination is already in the cache, and
	# if yes, return the stored value from there since we already
	# know the number of possible prize strings from this point on
	__A :			List[Any]		    =			(days, absent, late)
	if key in cache:
		return cache[key]

	# now we calculate the three possible ways that can unfold from
	# this point on, depending on our attendance today

	# 1) if we are late (but not absent), the "absent" counter stays as
	# it is, but the "late" counter increases by one
	__A :			Dict		    =			_calculate(days - 1			,a__			,late + 1       )

	# 2) if we are absent, the "absent" counter increases by 1, and the
	# "late" counter resets to 0
	__A :			List[str]		    =			_calculate(days - 1			,absent + 1			,0       )

	# 3) if we are on time, this resets the "late" counter and keeps the
	# absent counter
	__A :			int		    =			_calculate(days - 1			,a__			,0       )

	__A :			Optional[int]		    =			state_late + state_absent + state_ontime

	__A :			Tuple		    =			prizestrings
	return prizestrings
def 							__SCREAMING_SNAKE_CASE     (   a__    :   int = 30       )					->				int:
	return _calculate(a__			,absent=0			,late=0       )


if __name__ == "__main__":
			print(solution())





