





from typing import List, Optional, Union

import torch

from ...models import UNetaDConditionModel, VQModel
from ...pipelines import DiffusionPipeline
from ...pipelines.pipeline_utils import ImagePipelineOutput
from ...schedulers import DDPMScheduler
from ...utils import (
    is_accelerate_available,
    is_accelerate_version,
    logging,
    randn_tensor,
    replace_example_docstring,
)


UpperCamelCase__   : List[str]					  = logging.get_logger(__name__)  # pylint: disable=invalid-name

UpperCamelCase__   : List[Any]					  = """
    Examples:
        ```py
        >>> from diffusers import KandinskyV22Pipeline, KandinskyV22PriorPipeline
        >>> import torch

        >>> pipe_prior = KandinskyV22PriorPipeline.from_pretrained(\"kandinsky-community/kandinsky-2-2-prior\")
        >>> pipe_prior.to(\"cuda\")
        >>> prompt = \"red cat, 4k photo\"
        >>> out = pipe_prior(prompt)
        >>> image_emb = out.image_embeds
        >>> zero_image_emb = out.negative_image_embeds
        >>> pipe = KandinskyV22Pipeline.from_pretrained(\"kandinsky-community/kandinsky-2-2-decoder\")
        >>> pipe.to(\"cuda\")
        >>> image = pipe(
        ...     image_embeds=image_emb,
        ...     negative_image_embeds=zero_image_emb,
        ...     height=768,
        ...     width=768,
        ...     num_inference_steps=50,
        ... ).images
        >>> image[0].save(\"cat.png\")
        ```
"""




def    A_(			A				,      A				,      A=8   ):
	UpperCAmelCase_								=     height // scale_factor**2
	if height % scale_factor**2 != 0:
		new_height += 1
	UpperCAmelCase_								=     width // scale_factor**2
	if width % scale_factor**2 != 0:
		new_width += 1
	return new_height * scale_factor, new_width * scale_factor







class   _UpperCamelCase  (       A_  ):







					'''simple docstring'''

					def __init__(						self    :  List[Any] ,					__lowercase    :  UNetaDConditionModel ,					__lowercase    :  DDPMScheduler ,					__lowercase    :  VQModel ,					):






						'''simple docstring'''







						super().__init__()

						self.register_modules(
						    unet=__lowercase ,					scheduler=__lowercase ,					movq=__lowercase ,					)
						UpperCAmelCase_								=     2 ** (len(self.movq.config.block_out_channels		) - 1)





					def        SCREAMING_SNAKE_CASE							(						self    :  str ,					__lowercase    :  Optional[int] ,					__lowercase    :  Dict ,					__lowercase    :  List[Any] ,					__lowercase    :  int ,					__lowercase    :  Optional[int] ,					__lowercase    :  Dict		):






						'''simple docstring'''







						if latents is None:
							UpperCAmelCase_								=     randn_tensor(__lowercase ,					generator=__lowercase ,					device=__lowercase ,					dtype=__lowercase		)
						else:
							if latents.shape != shape:
								raise ValueError(F"""Unexpected latents shape, got {latents.shape}, expected {shape}"""		)
							UpperCAmelCase_								=     latents.to(__lowercase		)

						UpperCAmelCase_								=     latents * scheduler.init_noise_sigma
						return latents





					def        SCREAMING_SNAKE_CASE							(						self    :  Optional[Any] ,					__lowercase    :  int=0		):






						'''simple docstring'''







						if is_accelerate_available():
							from accelerate import cpu_offload
						else:
							raise ImportError("""Please install accelerate via `pip install accelerate`"""		)

						UpperCAmelCase_								=     torch.device(F"""cuda:{gpu_id}"""		)

						UpperCAmelCase_								=     [
						    self.unet,
						    self.movq,
						]
						for cpu_offloaded_model in models:
							if cpu_offloaded_model is not None:
								cpu_offload(__lowercase ,					__lowercase		)





					def        SCREAMING_SNAKE_CASE							(						self    :  Optional[Any] ,					__lowercase    :  int=0		):






						'''simple docstring'''







						if is_accelerate_available() and is_accelerate_version(""">=""" ,					"""0.17.0.dev0"""		):
							from accelerate import cpu_offload_with_hook
						else:
							raise ImportError("""`enable_model_cpu_offload` requires `accelerate v0.17.0` or higher."""		)

						UpperCAmelCase_								=     torch.device(F"""cuda:{gpu_id}"""		)

						if self.device.type != "cpu":
							self.to("""cpu""" ,					silence_dtype_warnings=__lowercase		)
							torch.cuda.empty_cache()  # otherwise we don't see the memory savings (but they probably exist)

						UpperCAmelCase_								=     None
						for cpu_offloaded_model in [self.unet, self.movq]:
							UpperCAmelCase_						,	UpperCAmelCase_								=     cpu_offload_with_hook(__lowercase ,					__lowercase ,					prev_module_hook=__lowercase		)

						# We'll offload the last model manually.
						UpperCAmelCase_								=     hook





					@property
					# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._execution_device
					def        SCREAMING_SNAKE_CASE							(						self    :  int		):






						'''simple docstring'''







						if not hasattr(self.unet ,					"""_hf_hook"""		):
							return self.device
						for module in self.unet.modules():
							if (
							    hasattr(__lowercase ,					"""_hf_hook"""		)
							    and hasattr(module._hf_hook ,					"""execution_device"""		)
							    and module._hf_hook.execution_device is not None
							):
								return torch.device(module._hf_hook.execution_device		)
						return self.device





					@torch.no_grad()
					@replace_example_docstring(__lowercase		)
					def __call__(						self    :  Union[str, Any] ,					__lowercase    :  Union[torch.FloatTensor, List[torch.FloatTensor]] ,					__lowercase    :  Union[torch.FloatTensor, List[torch.FloatTensor]] ,					__lowercase    :  int = 5_12 ,					__lowercase    :  int = 5_12 ,					__lowercase    :  int = 1_00 ,					__lowercase    :  float = 4.0 ,					__lowercase    :  int = 1 ,					__lowercase    :  Optional[Union[torch.Generator, List[torch.Generator]]] = None ,					__lowercase    :  Optional[torch.FloatTensor] = None ,					__lowercase    :  Optional[str] = "pil" ,					__lowercase    :  bool = True ,					):






						'''simple docstring'''







						UpperCAmelCase_								=     self._execution_device

						UpperCAmelCase_								=     guidance_scale > 1.0

						if isinstance(__lowercase ,					__lowercase		):
							UpperCAmelCase_								=     torch.cat(__lowercase ,					dim=0		)
						UpperCAmelCase_								=     image_embeds.shape[0] * num_images_per_prompt
						if isinstance(__lowercase ,					__lowercase		):
							UpperCAmelCase_								=     torch.cat(__lowercase ,					dim=0		)

						if do_classifier_free_guidance:
							UpperCAmelCase_								=     image_embeds.repeat_interleave(__lowercase ,					dim=0		)
							UpperCAmelCase_								=     negative_image_embeds.repeat_interleave(__lowercase ,					dim=0		)

						UpperCAmelCase_								=     torch.cat([negative_image_embeds, image_embeds] ,					dim=0		).to(dtype=self.unet.dtype ,					device=__lowercase		)

						self.scheduler.set_timesteps(__lowercase ,					device=__lowercase		)
						UpperCAmelCase_								=     self.scheduler.timesteps

						UpperCAmelCase_								=     self.unet.config.in_channels

						UpperCAmelCase_						,	UpperCAmelCase_								=     downscale_height_and_width(__lowercase ,					__lowercase ,					self.movq_scale_factor		)

						# create initial latent
						UpperCAmelCase_								=     self.prepare_latents(
						    (batch_size, num_channels_latents, height, width) ,					image_embeds.dtype ,					__lowercase ,					__lowercase ,					__lowercase ,					self.scheduler ,					)

						for i, t in enumerate(self.progress_bar(__lowercase		)		):
							# expand the latents if we are doing classifier free guidance
							UpperCAmelCase_								=     torch.cat([latents] * 2		) if do_classifier_free_guidance else latents

							UpperCAmelCase_								=     {"""image_embeds""": image_embeds}
							UpperCAmelCase_								=     self.unet(
							    sample=__lowercase ,					timestep=__lowercase ,					encoder_hidden_states=__lowercase ,					added_cond_kwargs=__lowercase ,					return_dict=__lowercase ,					)[0]

							if do_classifier_free_guidance:
								UpperCAmelCase_						,	UpperCAmelCase_								=     noise_pred.split(latents.shape[1] ,					dim=1		)
								UpperCAmelCase_						,	UpperCAmelCase_								=     noise_pred.chunk(2		)
								UpperCAmelCase_						,	UpperCAmelCase_								=     variance_pred.chunk(2		)
								UpperCAmelCase_								=     noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
								UpperCAmelCase_								=     torch.cat([noise_pred, variance_pred_text] ,					dim=1		)

							if not (
							    hasattr(self.scheduler.config ,					"""variance_type"""		)
							    and self.scheduler.config.variance_type in ["learned", "learned_range"]
							):
								UpperCAmelCase_						,	UpperCAmelCase_								=     noise_pred.split(latents.shape[1] ,					dim=1		)

							# compute the previous noisy sample x_t -> x_t-1
							UpperCAmelCase_								=     self.scheduler.step(
							    __lowercase ,					__lowercase ,					__lowercase ,					generator=__lowercase ,					)[0]
						# post-processing
						UpperCAmelCase_								=     self.movq.decode(__lowercase ,					force_not_quantize=__lowercase		)["""sample"""]

						if output_type not in ["pt", "np", "pil"]:
							raise ValueError(F"""Only the output types `pt`, `pil` and `np` are supported not output_type={output_type}"""		)

						if output_type in ["np", "pil"]:
							UpperCAmelCase_								=     image * 0.5 + 0.5
							UpperCAmelCase_								=     image.clamp(0 ,					1		)
							UpperCAmelCase_								=     image.cpu().permute(0 ,					2 ,					3 ,					1		).float().numpy()

						if output_type == "pil":
							UpperCAmelCase_								=     self.numpy_to_pil(__lowercase		)

						if not return_dict:
							return (image,)

						return ImagePipelineOutput(images=__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()}")


