





import math
import time

from transformers import Trainer, is_torch_tpu_available
from transformers.trainer_utils import PredictionOutput, speed_metrics


if is_torch_tpu_available(check_device=False):
				import torch_xla.core.xla_model as xm
				import torch_xla.debug.metrics as met







class   _UpperCamelCase  (       A_  ):







					'''simple docstring'''

					def __init__(						self    :  List[str] ,					*__lowercase    :  List[str] ,					__lowercase    :  str=None ,					__lowercase    :  Tuple=None ,					**__lowercase    :  Optional[int]		):






						'''simple docstring'''







						super().__init__(*__lowercase ,					**__lowercase		)
						UpperCAmelCase_								=     eval_examples
						UpperCAmelCase_								=     post_process_function





					def        SCREAMING_SNAKE_CASE							(						self    :  Any ,					__lowercase    :  Tuple=None ,					__lowercase    :  List[str]=None ,					__lowercase    :  List[str]=None ,					__lowercase    :  str = "eval"		):






						'''simple docstring'''







						UpperCAmelCase_								=     self.eval_dataset if eval_dataset is None else eval_dataset
						UpperCAmelCase_								=     self.get_eval_dataloader(__lowercase		)
						UpperCAmelCase_								=     self.eval_examples if eval_examples is None else eval_examples

						# Temporarily disable metric computation, we will do it in the loop here.
						UpperCAmelCase_								=     self.compute_metrics
						UpperCAmelCase_								=     None
						UpperCAmelCase_								=     self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
						UpperCAmelCase_								=     time.time()
						try:
							UpperCAmelCase_								=     eval_loop(
							    __lowercase ,					description="""Evaluation""" ,					prediction_loss_only=True if compute_metrics is None else None ,					ignore_keys=__lowercase ,					metric_key_prefix=__lowercase ,					)
						finally:
							UpperCAmelCase_								=     compute_metrics
						UpperCAmelCase_								=     self.args.eval_batch_size * self.args.world_size
						if F"""{metric_key_prefix}_jit_compilation_time""" in output.metrics:
							start_time += output.metrics[F"""{metric_key_prefix}_jit_compilation_time"""]
						output.metrics.update(
						    speed_metrics(
						        __lowercase ,					__lowercase ,					num_samples=output.num_samples ,					num_steps=math.ceil(output.num_samples / total_batch_size		) ,					)		)
						if self.post_process_function is not None and self.compute_metrics is not None and self.args.should_save:
							# Only the main node write the results by default
							UpperCAmelCase_								=     self.post_process_function(__lowercase ,					__lowercase ,					output.predictions		)
							UpperCAmelCase_								=     self.compute_metrics(__lowercase		)

							# Prefix all keys with metric_key_prefix + '_'
							for key in list(metrics.keys()		):
								if not key.startswith(F"""{metric_key_prefix}_"""		):
									UpperCAmelCase_								=     metrics.pop(__lowercase		)
							metrics.update(output.metrics		)
						else:
							UpperCAmelCase_								=     output.metrics

						if self.args.should_log:
							# Only the main node log the results by default
							self.log(__lowercase		)

						if self.args.tpu_metrics_debug or self.args.debug:
							# tpu-comment: Logging debug metrics for PyTorch/XLA (compile, execute times, ops, etc.)
							xm.master_print(met.metrics_report()		)

						UpperCAmelCase_								=     self.callback_handler.on_evaluate(self.args ,					self.state ,					self.control ,					__lowercase		)
						return metrics





					def        SCREAMING_SNAKE_CASE							(						self    :  str ,					__lowercase    :  Optional[Any] ,					__lowercase    :  Optional[int] ,					__lowercase    :  Any=None ,					__lowercase    :  str = "test"		):






						'''simple docstring'''







						UpperCAmelCase_								=     self.get_test_dataloader(__lowercase		)

						# Temporarily disable metric computation, we will do it in the loop here.
						UpperCAmelCase_								=     self.compute_metrics
						UpperCAmelCase_								=     None
						UpperCAmelCase_								=     self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
						UpperCAmelCase_								=     time.time()
						try:
							UpperCAmelCase_								=     eval_loop(
							    __lowercase ,					description="""Prediction""" ,					prediction_loss_only=True if compute_metrics is None else None ,					ignore_keys=__lowercase ,					metric_key_prefix=__lowercase ,					)
						finally:
							UpperCAmelCase_								=     compute_metrics
						UpperCAmelCase_								=     self.args.eval_batch_size * self.args.world_size
						if F"""{metric_key_prefix}_jit_compilation_time""" in output.metrics:
							start_time += output.metrics[F"""{metric_key_prefix}_jit_compilation_time"""]
						output.metrics.update(
						    speed_metrics(
						        __lowercase ,					__lowercase ,					num_samples=output.num_samples ,					num_steps=math.ceil(output.num_samples / total_batch_size		) ,					)		)

						if self.post_process_function is None or self.compute_metrics is None:
							return output

						UpperCAmelCase_								=     self.post_process_function(__lowercase ,					__lowercase ,					output.predictions ,					"""predict"""		)
						UpperCAmelCase_								=     self.compute_metrics(__lowercase		)

						# Prefix all keys with metric_key_prefix + '_'
						for key in list(metrics.keys()		):
							if not key.startswith(F"""{metric_key_prefix}_"""		):
								UpperCAmelCase_								=     metrics.pop(__lowercase		)
						metrics.update(output.metrics		)
						return PredictionOutput(predictions=predictions.predictions ,					label_ids=predictions.label_ids ,					metrics=__lowercase		)









from math import factorial

UpperCamelCase__   : dict[str, int]					  = {str(digit): factorial(digit) for digit in range(10)}




def    A_(			A   ):
	if not isinstance(A				,      A   ):
		raise TypeError("""Parameter number must be int"""   )

	if number < 0:
		raise ValueError("""Parameter number must be greater than or equal to 0"""   )

	# Converts number in string to iterate on its digits and adds its factorial.
	return sum(DIGIT_FACTORIAL[digit] for digit in str(A   )   )




def    A_(			A = 60				,      A = 1000000   ):

	if not isinstance(A				,      A   ) or not isinstance(A				,      A   ):
		raise TypeError("""Parameters chain_length and number_limit must be int"""   )

	if chain_length <= 0 or number_limit <= 0:
		raise ValueError(
		    """Parameters chain_length and number_limit must be greater than 0"""   )

	# the counter for the chains with the exact desired length
	UpperCAmelCase_								=     0
	# the cached sizes of the previous chains
	UpperCAmelCase_								=     {}

	for start_chain_element in range(1				,      A   ):
		# The temporary set will contain the elements of the chain
		UpperCAmelCase_								=     set()
		UpperCAmelCase_								=     0

		# Stop computing the chain when you find a cached size, a repeating item or the
		# length is greater then the desired one.
		UpperCAmelCase_								=     start_chain_element
		while (
		    chain_element not in chain_sets_lengths
		    and chain_element not in chain_set
		    and chain_set_length <= chain_length
		):
			chain_set.add(A   )
			chain_set_length += 1
			UpperCAmelCase_								=     digit_factorial_sum(A   )

		if chain_element in chain_sets_lengths:
			chain_set_length += chain_sets_lengths[chain_element]

		UpperCAmelCase_								=     chain_set_length

		# If chain contains the exact amount of elements increase the counter
		if chain_set_length == chain_length:
			chains_counter += 1

	return chains_counter


if __name__ == "__main__":
				import doctest

				doctest.testmod()
				print(f"{solution()}")


