


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

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


__snake_case							      =     logging.get_logger(__name__)

__snake_case							      =     {
    '''vocab_file''': '''vocab.txt''',
    '''merges_file''': '''bpe.codes''',
}

__snake_case							      =     {
    '''vocab_file''': {
        '''vinai/phobert-base''': '''https://huggingface.co/vinai/phobert-base/resolve/main/vocab.txt''',
        '''vinai/phobert-large''': '''https://huggingface.co/vinai/phobert-large/resolve/main/vocab.txt''',
    },
    '''merges_file''': {
        '''vinai/phobert-base''': '''https://huggingface.co/vinai/phobert-base/resolve/main/bpe.codes''',
        '''vinai/phobert-large''': '''https://huggingface.co/vinai/phobert-large/resolve/main/bpe.codes''',
    },
}

__snake_case							      =     {
    '''vinai/phobert-base''': 256,
    '''vinai/phobert-large''': 256,
}


def 			a      (			__a   )  ->	Optional[Any]:



					'''simple docstring'''






					UpperCamelCase__   :str												= set()
					UpperCamelCase__   :Dict												= word[0]
					for char in word[1:]:
										pairs.add((prev_char, char)   )
										UpperCamelCase__   :Tuple												= char

					UpperCamelCase__   :List[Any]												= set(__a   )
					return pairs







class    lowercase	(							A__					):

		"""simple docstring"""

		_a     =				VOCAB_FILES_NAMES
		_a     =				PRETRAINED_VOCAB_FILES_MAP
		_a     =				PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES




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

							'''simple docstring'''


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

							UpperCamelCase__   :Optional[Any]												= vocab_file
							UpperCamelCase__   :Any												= merges_file

							UpperCamelCase__   :str												= {}
							UpperCamelCase__   :Tuple												= 0
							UpperCamelCase__   :Any												= 1
							UpperCamelCase__   :Optional[Any]												= 2
							UpperCamelCase__   :str												= 3

							self.add_from_file(UpperCamelCase_							)

							UpperCamelCase__   :Union[str, Any]												= {v: k for k, v in self.encoder.items()}

							with open(UpperCamelCase_    ,   encoding='''utf-8'''							) as merges_handle:
												UpperCamelCase__   :List[str]												= merges_handle.read().split('''\n'''							)[:-1]
							UpperCamelCase__   :Tuple												= [tuple(merge.split()[:-1]							) for merge in merges]
							UpperCamelCase__   :List[Any]												= dict(zip(UpperCamelCase_    ,   range(len(UpperCamelCase_							)							)							)							)
							UpperCamelCase__   :Tuple												= {}




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

							'''simple docstring'''


							if token_ids_a is None:
												return [self.cls_token_id] + token_ids_a + [self.sep_token_id]
							UpperCamelCase__   :Union[str, Any]												= [self.cls_token_id]
							UpperCamelCase__   :List[Any]												= [self.sep_token_id]
							return cls + token_ids_a + sep + sep + token_ids_a + sep




		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_							)) + [1]
							return [1] + ([0] * len(UpperCamelCase_							)) + [1, 1] + ([0] * len(UpperCamelCase_							)) + [1]




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

							'''simple docstring'''


							UpperCamelCase__   :Tuple												= [self.sep_token_id]
							UpperCamelCase__   :int												= [self.cls_token_id]

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




		@property
		def     lowerCAmelCase__				(		self							):

							'''simple docstring'''


							return len(self.encoder							)




		def     lowerCAmelCase__				(		self							):

							'''simple docstring'''


							return dict(self.encoder    ,   **self.added_tokens_encoder							)




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							if token in self.cache:
												return self.cache[token]
							UpperCamelCase__   :List[Any]												= tuple(UpperCamelCase_							)
							UpperCamelCase__   :int												= tuple(list(word[:-1]							) + [word[-1] + '''</w>''']							)
							UpperCamelCase__   :Dict												= get_pairs(UpperCamelCase_							)

							if not pairs:
												return token

							while True:
												UpperCamelCase__   :Dict												= min(UpperCamelCase_    ,   key=lambda UpperCamelCase_							: self.bpe_ranks.get(UpperCamelCase_    ,   float('''inf'''							)							)							)
												if bigram not in self.bpe_ranks:
																	break
												UpperCamelCase__					,				UpperCamelCase__   :List[str]												= bigram
												UpperCamelCase__   :Union[str, Any]												= []
												UpperCamelCase__   :Any												= 0
												while i < len(UpperCamelCase_							):
																	try:
																						UpperCamelCase__   :Any												= word.index(UpperCamelCase_    ,   UpperCamelCase_							)
																	except ValueError:
																						new_word.extend(word[i:]							)
																						break
																	else:
																						new_word.extend(word[i:j]							)
																						UpperCamelCase__   :Any												= j

																	if word[i] == first and i < len(UpperCamelCase_							) - 1 and word[i + 1] == second:
																						new_word.append(first + second							)
																						i += 2
																	else:
																						new_word.append(word[i]							)
																						i += 1
												UpperCamelCase__   :Optional[int]												= tuple(UpperCamelCase_							)
												UpperCamelCase__   :List[str]												= new_word
												if len(UpperCamelCase_							) == 1:
																	break
												else:
																	UpperCamelCase__   :Tuple												= get_pairs(UpperCamelCase_							)
							UpperCamelCase__   :str												= '''@@ '''.join(UpperCamelCase_							)
							UpperCamelCase__   :Optional[Any]												= word[:-4]
							UpperCamelCase__   :Any												= word
							return word




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							UpperCamelCase__   :List[Any]												= []

							UpperCamelCase__   :Optional[Any]												= re.findall(r'''\S+\n?'''    ,   UpperCamelCase_							)

							for token in words:
												split_tokens.extend(list(self.bpe(UpperCamelCase_							).split(''' '''							)							)							)
							return split_tokens




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							return self.encoder.get(UpperCamelCase_    ,   self.encoder.get(self.unk_token							)							)




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							return self.decoder.get(UpperCamelCase_    ,   self.unk_token							)




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							UpperCamelCase__   :Dict												= ''' '''.join(UpperCamelCase_							).replace('''@@ '''    ,   ''''''							).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__   :Any												= os.path.join(
							    UpperCamelCase_    ,   (filename_prefix + '''-''' if filename_prefix else '''''') + VOCAB_FILES_NAMES['''vocab_file''']							)
							UpperCamelCase__   :int												= os.path.join(
							    UpperCamelCase_    ,   (filename_prefix + '''-''' if filename_prefix else '''''') + VOCAB_FILES_NAMES['''merges_file''']							)

							if os.path.abspath(self.vocab_file							) != os.path.abspath(UpperCamelCase_							):
												copyfile(self.vocab_file    ,   UpperCamelCase_							)

							if os.path.abspath(self.merges_file							) != os.path.abspath(UpperCamelCase_							):
												copyfile(self.merges_file    ,   UpperCamelCase_							)

							return out_vocab_file, out_merge_file




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							if isinstance(UpperCamelCase_    ,   UpperCamelCase_							):
												try:
																	with open(UpperCamelCase_    ,   '''r'''    ,   encoding='''utf-8'''							) as fd:
																						self.add_from_file(UpperCamelCase_							)
												except FileNotFoundError as fnfe:
																	raise fnfe
												except UnicodeError:
																	raise Exception(F'''Incorrect encoding detected in {f}, please rebuild the dataset'''							)
												return

							UpperCamelCase__   :Union[str, Any]												= f.readlines()
							for lineTmp in lines:
												UpperCamelCase__   :Optional[Any]												= lineTmp.strip()
												UpperCamelCase__   :Optional[Any]												= line.rfind(''' '''							)
												if idx == -1:
																	raise ValueError('''Incorrect dictionary format, expected \'<token> <cnt>\''''							)
												UpperCamelCase__   :List[Any]												= line[:idx]
												UpperCamelCase__   :Dict												= len(self.encoder							)



'''simple docstring'''
from collections import defaultdict
class    lowercase	:

		"""simple docstring"""

		def __init__(		self    ,   UpperCamelCase_    ,   UpperCamelCase_							):

							'''simple docstring'''


							UpperCamelCase__   :List[Any]												= total  # total no of tasks (N)

							# DP table will have a dimension of (2^M)*N
							# initially all values are set to -1
							UpperCamelCase__   :Union[str, Any]												= [
							    [-1 for i in range(total + 1							)] for j in range(2 ** len(UpperCamelCase_							)							)
							]

							UpperCamelCase__   :str												= defaultdict(UpperCamelCase_							)  # stores the list of persons for each task

							# final_mask is used to check if all persons are included by setting all bits
							# to 1
							UpperCamelCase__   :Optional[int]												= (1 << len(UpperCamelCase_							)) - 1




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_    ,   UpperCamelCase_							):

							'''simple docstring'''


							if mask == self.final_mask:
												return 1

							# if not everyone gets the task and no more tasks are available, return 0
							if task_no > self.total_tasks:
												return 0

							# if case already considered
							if self.dp[mask][task_no] != -1:
												return self.dp[mask][task_no]

							# Number of ways when we don't this task in the arrangement
							UpperCamelCase__   :str												= self.count_ways_until(UpperCamelCase_    ,   task_no + 1							)

							# now assign the tasks one by one to all possible persons and recursively
							# assign for the remaining tasks.
							if task_no in self.task:
												for p in self.task[task_no]:
																	# if p is already given a task
																	if mask & (1 << p):
																						continue

																	# assign this task to p and change the mask value. And recursively
																	# assign tasks with the new mask value.
																	total_ways_util += self.count_ways_until(mask | (1 << p)    ,   task_no + 1							)

        # save the value.
							UpperCamelCase__   :Optional[int]												= total_ways_util

							return self.dp[mask][task_no]




		def     lowerCAmelCase__				(		self    ,   UpperCamelCase_							):

							'''simple docstring'''


							for i in range(len(UpperCamelCase_							)							):
												for j in task_performed[i]:
																	self.task[j].append(UpperCamelCase_							)

        # call the function to fill the DP table, final answer is stored in dp[0][1]
							return self.count_ways_until(0    ,   1							)


if __name__ == "__main__":
		__snake_case							      =     5  # total no of tasks (the value of N)

		# the list of tasks that can be done by M persons.
		__snake_case							      =     [[1, 3, 4], [1, 2, 5], [3, 4]]
		print(
		    AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
		        task_performed
		    )
		)