


'''simple docstring'''
import os
from shutil import copyfile
from typing import Any, Dict, List, Optional, Tuple

import sentencepiece as spm

from ...tokenization_utils import PreTrainedTokenizer
from ...utils import logging


__snake_case											=					logging.get_logger(__name__)

__snake_case											=					'''▁'''

__snake_case											=					{'''vocab_file''': '''sentencepiece.bpe.model'''}

__snake_case											=					{
    '''vocab_file''': {
        '''facebook/xglm-564M''': '''https://huggingface.co/facebook/xglm-564M/resolve/main/sentencepiece.bpe.model''',
    }
}

__snake_case											=					{
    '''facebook/xglm-564M''': 2048,
}
class        lowercase     (							A__ ):

		"""simple docstring"""

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




		def __init__(		self   ,       UpperCamelCase_   ,       UpperCamelCase_="<s>"   ,       UpperCamelCase_="</s>"   ,       UpperCamelCase_="</s>"   ,       UpperCamelCase_="<s>"   ,       UpperCamelCase_="<unk>"   ,       UpperCamelCase_="<pad>"   ,       UpperCamelCase_ = None   ,       **UpperCamelCase_   ,       ):

							'''simple docstring'''


							UpperCamelCase__       :Any							 =			{} if sp_model_kwargs is None else sp_model_kwargs

							# Compatibility with the original tokenizer
							UpperCamelCase__       :List[str]							 =			7
							UpperCamelCase__       :List[str]							 =			[F'''<madeupword{i}>''' for i in range(self.num_madeup_words							)]

							UpperCamelCase__       :Optional[int]							 =			kwargs.get('''additional_special_tokens'''   ,       []							)
							kwargs["additional_special_tokens"] += [
							    word for word in madeup_words if word not in kwargs["additional_special_tokens"]
							]

							super().__init__(
							    bos_token=UpperCamelCase_   ,       eos_token=UpperCamelCase_   ,       unk_token=UpperCamelCase_   ,       sep_token=UpperCamelCase_   ,       cls_token=UpperCamelCase_   ,       pad_token=UpperCamelCase_   ,       sp_model_kwargs=self.sp_model_kwargs   ,       **UpperCamelCase_   ,       )

							UpperCamelCase__       :Optional[int]							 =			spm.SentencePieceProcessor(**self.sp_model_kwargs							)
							self.sp_model.Load(str(UpperCamelCase_							)							)
							UpperCamelCase__       :Any							 =			vocab_file

							# Original fairseq vocab and spm vocab must be "aligned":
							# Vocab    |    0    |    1    |   2    |    3    |  4  |  5  |  6  |   7   |   8   |  9
							# -------- | ------- | ------- | ------ | ------- | --- | --- | --- | ----- | ----- | ----
							# fairseq  | '<s>'   | '<pad>' | '</s>' | '<unk>' | ',' | '.' | '▁' | 's'   | '▁de' | '-'
							# spm      | '<unk>' | '<s>'   | '</s>' | ','     | '.' | '▁' | 's' | '▁de' | '-'   | '▁a'

							# The first "real" token "," has position 4 in the original fairseq vocab and position 3 in the spm vocab
							UpperCamelCase__       :Tuple							 =			1

							# Mimic fairseq token-to-id alignment for the first 4 token
							UpperCamelCase__       :int							 =			{'''<s>''': 0, '''<pad>''': 1, '''</s>''': 2, '''<unk>''': 3}

							UpperCamelCase__       :Optional[Any]							 =			len(self.sp_model							)
							UpperCamelCase__       :str							 =			{F'''<madeupword{i}>''': sp_size + i + self.fairseq_offset for i in range(self.num_madeup_words							)}
							self.fairseq_tokens_to_ids.update(UpperCamelCase_							)

							UpperCamelCase__       :int							 =			{v: k for k, v in self.fairseq_tokens_to_ids.items()}




		def __getstate__(		self							):

							'''simple docstring'''


							UpperCamelCase__       :Dict							 =			self.__dict__.copy()
							UpperCamelCase__       :List[Any]							 =			None
							UpperCamelCase__       :List[str]							 =			self.sp_model.serialized_model_proto()
							return state




		def __setstate__(		self   ,       UpperCamelCase_							):

							'''simple docstring'''


							UpperCamelCase__       :Tuple							 =			d

							# for backward compatibility
							if not hasattr(self   ,       '''sp_model_kwargs'''							):
												UpperCamelCase__       :Tuple							 =			{}

							UpperCamelCase__       :List[str]							 =			spm.SentencePieceProcessor(**self.sp_model_kwargs							)
							self.sp_model.LoadFromSerializedProto(self.sp_model_proto							)




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_   ,       UpperCamelCase_ = None							):

							'''simple docstring'''


							if token_ids_a is None:
												return [self.sep_token_id] + token_ids_a
							UpperCamelCase__       :Optional[int]							 =			[self.sep_token_id]
							return sep + token_ids_a + sep + sep + token_ids_a




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_   ,       UpperCamelCase_ = None   ,       UpperCamelCase_ = False							):

							'''simple docstring'''


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

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




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_   ,       UpperCamelCase_ = None							):

							'''simple docstring'''


							UpperCamelCase__       :Tuple							 =			[self.sep_token_id]

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




		@property
		def    lowerCAmelCase__    (		self							):

							'''simple docstring'''


							return len(self.sp_model							) + self.fairseq_offset + self.num_madeup_words




		def    lowerCAmelCase__    (		self							):

							'''simple docstring'''


							UpperCamelCase__       :Tuple							 =			{self.convert_ids_to_tokens(UpperCamelCase_							): i for i in range(self.vocab_size							)}
							vocab.update(self.added_tokens_encoder							)
							return vocab




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_							):

							'''simple docstring'''


							return self.sp_model.encode(UpperCamelCase_   ,       out_type=UpperCamelCase_							)




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_							):

							'''simple docstring'''


							if token in self.fairseq_tokens_to_ids:
												return self.fairseq_tokens_to_ids[token]
							UpperCamelCase__       :Tuple							 =			self.sp_model.PieceToId(UpperCamelCase_							)

							# Need to return unknown token if the SP model returned 0
							return spm_id + self.fairseq_offset if spm_id else self.unk_token_id




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_							):

							'''simple docstring'''


							if index in self.fairseq_ids_to_tokens:
												return self.fairseq_ids_to_tokens[index]
							return self.sp_model.IdToPiece(index - self.fairseq_offset							)




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_							):

							'''simple docstring'''


							UpperCamelCase__       :Tuple							 =			''''''.join(UpperCamelCase_							).replace(UpperCamelCase_   ,       ''' '''							).strip()
							return out_string




		def    lowerCAmelCase__    (		self   ,       UpperCamelCase_   ,       UpperCamelCase_ = None							):

							'''simple docstring'''


							if not os.path.isdir(UpperCamelCase_							):
												logger.error(F'''Vocabulary path ({save_directory}) should be a directory'''							)
												return
							UpperCamelCase__       :Optional[int]							 =			os.path.join(
							    UpperCamelCase_   ,       (filename_prefix + '''-''' if filename_prefix else '''''') + VOCAB_FILES_NAMES['''vocab_file''']							)

							if os.path.abspath(self.vocab_file							) != os.path.abspath(UpperCamelCase_							) and os.path.isfile(self.vocab_file							):
												copyfile(self.vocab_file   ,       UpperCamelCase_							)
							elif not os.path.isfile(self.vocab_file							):
												with open(UpperCamelCase_   ,       '''wb'''							) as fi:
																	UpperCamelCase__       :Union[str, Any]							 =			self.sp_model.serialized_model_proto()
																	fi.write(UpperCamelCase_							)

							return (out_vocab_file,)



'''simple docstring'''
from collections import Counter
from timeit import timeit


def       a				(      __a = ""			, )  ->     bool:



					'''simple docstring'''






					return sum(c % 2 for c in Counter(input_str.replace(''' '''			, ''''''       ).lower()       ).values()       ) < 2


def       a				(      __a = ""       )  ->     bool:



					'''simple docstring'''






					if len(__a       ) == 0:
										return True
					UpperCamelCase__       :List[Any]							 =			input_str.replace(''' '''			, ''''''       ).lower()
					# character_freq_dict: Stores the frequency of every character in the input string
					UpperCamelCase__       :dict[str, int]							 =			{}

					for character in lower_case_input_str:
										UpperCamelCase__       :Optional[int]							 =			character_freq_dict.get(__a			, 0       ) + 1
					UpperCamelCase__       :List[str]							 =			0

					for character_count in character_freq_dict.values():
										if character_count % 2:
															odd_char += 1
					if odd_char > 1:
										return False
					return True


def       a				(      __a = ""       )  ->     None:



					'''simple docstring'''






					print('''\nFor string = '''			, __a			, ''':'''       )
					print(
					    '''> can_string_be_rearranged_as_palindrome_counter()'''			, '''\tans ='''			, can_string_be_rearranged_as_palindrome_counter(__a       )			, '''\ttime ='''			, timeit(
					        '''z.can_string_be_rearranged_as_palindrome_counter(z.check_str)'''			, setup='''import __main__ as z'''			, )			, '''seconds'''			, )
					print(
					    '''> can_string_be_rearranged_as_palindrome()'''			, '''\tans ='''			, can_string_be_rearranged_as_palindrome(__a       )			, '''\ttime ='''			, timeit(
					        '''z.can_string_be_rearranged_as_palindrome(z.check_str)'''			, setup='''import __main__ as z'''			, )			, '''seconds'''			, )


if __name__ == "__main__":
		__snake_case											=					input(
		    '''Enter string to determine if it can be rearranged as a palindrome or not: '''
		).strip()
		benchmark(check_str)
		__snake_case											=					can_string_be_rearranged_as_palindrome_counter(check_str)
		print(F"""{check_str} can {'' if status else 'not '}be rearranged as a palindrome""")