






import argparse
import json
import pickle
from pathlib import Path

import requests
import torch
from huggingface_hub import hf_hub_download
from PIL import Image

from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, MaskFormerImageProcessor, SwinConfig
from transformers.utils import logging


logging.set_verbosity_info()
__snake_case    :    List[Any]         =     logging.get_logger(__name__)







def 	_UpperCamelCase   (    UpperCamelCase_       :					str		):

						"""simple docstring"""



						lowerCAmelCase__    						=						SwinConfig.from_pretrained(
						    'microsoft/swin-tiny-patch4-window7-224'    ,       out_features=['stage1', 'stage2', 'stage3', 'stage4']		)
						lowerCAmelCase__    						=						MaskFormerConfig(backbone_config=UpperCamelCase_		)

						lowerCAmelCase__    						=						'huggingface/label-files'
						if "ade20k-full" in model_name:
												# this should be ok
												lowerCAmelCase__    						=						847
												lowerCAmelCase__    						=						'maskformer-ade20k-full-id2label.json'
						elif "ade" in model_name:
												# this should be ok
												lowerCAmelCase__    						=						150
												lowerCAmelCase__    						=						'ade20k-id2label.json'
						elif "coco-stuff" in model_name:
												# this should be ok
												lowerCAmelCase__    						=						171
												lowerCAmelCase__    						=						'maskformer-coco-stuff-id2label.json'
						elif "coco" in model_name:
												# TODO
												lowerCAmelCase__    						=						133
												lowerCAmelCase__    						=						'coco-panoptic-id2label.json'
						elif "cityscapes" in model_name:
												# this should be ok
												lowerCAmelCase__    						=						19
												lowerCAmelCase__    						=						'cityscapes-id2label.json'
						elif "vistas" in model_name:
												# this should be ok
												lowerCAmelCase__    						=						65
												lowerCAmelCase__    						=						'mapillary-vistas-id2label.json'

						lowerCAmelCase__    						=						json.load(open(hf_hub_download(UpperCamelCase_    ,       UpperCamelCase_    ,       repo_type='dataset'		)    ,       'r'		)		)
						lowerCAmelCase__    						=						{int(UpperCamelCase_		): v for k, v in idalabel.items()}

						return config







def 	_UpperCamelCase   (    UpperCamelCase_       :					List[str]		):

						"""simple docstring"""



						lowerCAmelCase__    						=						[]
						# stem
						# fmt: off
						rename_keys.append(('backbone.patch_embed.proj.weight', 'model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.weight')		)
						rename_keys.append(('backbone.patch_embed.proj.bias', 'model.pixel_level_module.encoder.model.embeddings.patch_embeddings.projection.bias')		)
						rename_keys.append(('backbone.patch_embed.norm.weight', 'model.pixel_level_module.encoder.model.embeddings.norm.weight')		)
						rename_keys.append(('backbone.patch_embed.norm.bias', 'model.pixel_level_module.encoder.model.embeddings.norm.bias')		)
						# stages
						for i in range(len(config.backbone_config.depths		)		):
												for j in range(config.backbone_config.depths[i]		):
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.norm1.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.norm1.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_before.bias")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.attn.relative_position_bias_table", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_bias_table")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.attn.relative_position_index", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.self.relative_position_index")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.attn.proj.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.attn.proj.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.attention.output.dense.bias")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.norm2.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.norm2.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.layernorm_after.bias")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.mlp.fc1.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.mlp.fc1.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.intermediate.dense.bias")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.mlp.fc2.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.blocks.{j}.mlp.fc2.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.blocks.{j}.output.dense.bias")		)

												if i < 3:
																		rename_keys.append((F"backbone.layers.{i}.downsample.reduction.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.reduction.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.downsample.norm.weight", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.weight")		)
																		rename_keys.append((F"backbone.layers.{i}.downsample.norm.bias", F"model.pixel_level_module.encoder.model.encoder.layers.{i}.downsample.norm.bias")		)
												rename_keys.append((F"backbone.norm{i}.weight", F"model.pixel_level_module.encoder.hidden_states_norms.{i}.weight")		)
												rename_keys.append((F"backbone.norm{i}.bias", F"model.pixel_level_module.encoder.hidden_states_norms.{i}.bias")		)

						# FPN
						rename_keys.append(('sem_seg_head.layer_4.weight', 'model.pixel_level_module.decoder.fpn.stem.0.weight')		)
						rename_keys.append(('sem_seg_head.layer_4.norm.weight', 'model.pixel_level_module.decoder.fpn.stem.1.weight')		)
						rename_keys.append(('sem_seg_head.layer_4.norm.bias', 'model.pixel_level_module.decoder.fpn.stem.1.bias')		)
						for source_index, target_index in zip(range(3    ,       0    ,       -1		)    ,       range(0    ,       3		)		):
												rename_keys.append((F"sem_seg_head.adapter_{source_index}.weight", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.0.weight")		)
												rename_keys.append((F"sem_seg_head.adapter_{source_index}.norm.weight", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.weight")		)
												rename_keys.append((F"sem_seg_head.adapter_{source_index}.norm.bias", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.proj.1.bias")		)
												rename_keys.append((F"sem_seg_head.layer_{source_index}.weight", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.0.weight")		)
												rename_keys.append((F"sem_seg_head.layer_{source_index}.norm.weight", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.weight")		)
												rename_keys.append((F"sem_seg_head.layer_{source_index}.norm.bias", F"model.pixel_level_module.decoder.fpn.layers.{target_index}.block.1.bias")		)
						rename_keys.append(('sem_seg_head.mask_features.weight', 'model.pixel_level_module.decoder.mask_projection.weight')		)
						rename_keys.append(('sem_seg_head.mask_features.bias', 'model.pixel_level_module.decoder.mask_projection.bias')		)

						# Transformer decoder
						for idx in range(config.decoder_config.decoder_layers		):
												# self-attention out projection
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.weight", F"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.out_proj.bias", F"model.transformer_module.decoder.layers.{idx}.self_attn.out_proj.bias")		)
												# cross-attention out projection
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.weight", F"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.out_proj.bias", F"model.transformer_module.decoder.layers.{idx}.encoder_attn.out_proj.bias")		)
												# MLP 1
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.weight", F"model.transformer_module.decoder.layers.{idx}.fc1.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear1.bias", F"model.transformer_module.decoder.layers.{idx}.fc1.bias")		)
												# MLP 2
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.weight", F"model.transformer_module.decoder.layers.{idx}.fc2.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.linear2.bias", F"model.transformer_module.decoder.layers.{idx}.fc2.bias")		)
												# layernorm 1 (self-attention layernorm)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.weight", F"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm1.bias", F"model.transformer_module.decoder.layers.{idx}.self_attn_layer_norm.bias")		)
												# layernorm 2 (cross-attention layernorm)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.weight", F"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm2.bias", F"model.transformer_module.decoder.layers.{idx}.encoder_attn_layer_norm.bias")		)
												# layernorm 3 (final layernorm)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.weight", F"model.transformer_module.decoder.layers.{idx}.final_layer_norm.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.norm3.bias", F"model.transformer_module.decoder.layers.{idx}.final_layer_norm.bias")		)

						rename_keys.append(('sem_seg_head.predictor.transformer.decoder.norm.weight', 'model.transformer_module.decoder.layernorm.weight')		)
						rename_keys.append(('sem_seg_head.predictor.transformer.decoder.norm.bias', 'model.transformer_module.decoder.layernorm.bias')		)

						# heads on top
						rename_keys.append(('sem_seg_head.predictor.query_embed.weight', 'model.transformer_module.queries_embedder.weight')		)

						rename_keys.append(('sem_seg_head.predictor.input_proj.weight', 'model.transformer_module.input_projection.weight')		)
						rename_keys.append(('sem_seg_head.predictor.input_proj.bias', 'model.transformer_module.input_projection.bias')		)

						rename_keys.append(('sem_seg_head.predictor.class_embed.weight', 'class_predictor.weight')		)
						rename_keys.append(('sem_seg_head.predictor.class_embed.bias', 'class_predictor.bias')		)

						for i in range(3		):
												rename_keys.append((F"sem_seg_head.predictor.mask_embed.layers.{i}.weight", F"mask_embedder.{i}.0.weight")		)
												rename_keys.append((F"sem_seg_head.predictor.mask_embed.layers.{i}.bias", F"mask_embedder.{i}.0.bias")		)
						# fmt: on

						return rename_keys







def 	_UpperCamelCase   (    UpperCamelCase_       :					Optional[int]    ,       UpperCamelCase_       :					Optional[Any]    ,       UpperCamelCase_       :					int		):

						"""simple docstring"""



						lowerCAmelCase__    						=						dct.pop(UpperCamelCase_		)
						lowerCAmelCase__    						=						val







def 	_UpperCamelCase   (    UpperCamelCase_       :					Dict    ,       UpperCamelCase_       :					Tuple		):

						"""simple docstring"""



						lowerCAmelCase__    						=						[int(backbone_config.embed_dim * 2**i		) for i in range(len(backbone_config.depths		)		)]
						for i in range(len(backbone_config.depths		)		):
												lowerCAmelCase__    						=						num_features[i]
												for j in range(backbone_config.depths[i]		):
																		# fmt: off
																		# read in weights + bias of input projection layer (in original implementation, this is a single matrix + bias)
																		lowerCAmelCase__    						=						state_dict.pop(F"backbone.layers.{i}.blocks.{j}.attn.qkv.weight"		)
																		lowerCAmelCase__    						=						state_dict.pop(F"backbone.layers.{i}.blocks.{j}.attn.qkv.bias"		)
																		# next, add query, keys and values (in that order) to the state dict
																		lowerCAmelCase__    						=						in_proj_weight[:dim, :]
																		lowerCAmelCase__    						=						in_proj_bias[: dim]
																		lowerCAmelCase__    						=						in_proj_weight[
																		    dim : dim * 2, :
																		]
																		lowerCAmelCase__    						=						in_proj_bias[
																		    dim : dim * 2
																		]
																		lowerCAmelCase__    						=						in_proj_weight[
																		    -dim :, :
																		]
																		lowerCAmelCase__    						=						in_proj_bias[-dim :]
																		# fmt: on







def 	_UpperCamelCase   (    UpperCamelCase_       :					Union[str, Any]    ,       UpperCamelCase_       :					str		):

						"""simple docstring"""



						lowerCAmelCase__    						=						config.decoder_config.hidden_size
						for idx in range(config.decoder_config.decoder_layers		):
												# read in weights + bias of self-attention input projection layer (in the original implementation, this is a single matrix + bias)
												lowerCAmelCase__    						=						state_dict.pop(F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_weight"		)
												lowerCAmelCase__    						=						state_dict.pop(F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.self_attn.in_proj_bias"		)
												# next, add query, keys and values (in that order) to the state dict
												lowerCAmelCase__    						=						in_proj_weight[: hidden_size, :]
												lowerCAmelCase__    						=						in_proj_bias[:config.hidden_size]
												lowerCAmelCase__    						=						in_proj_weight[hidden_size : hidden_size * 2, :]
												lowerCAmelCase__    						=						in_proj_bias[hidden_size : hidden_size * 2]
												lowerCAmelCase__    						=						in_proj_weight[-hidden_size :, :]
												lowerCAmelCase__    						=						in_proj_bias[-hidden_size :]
												# read in weights + bias of cross-attention input projection layer (in the original implementation, this is a single matrix + bias)
												lowerCAmelCase__    						=						state_dict.pop(F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_weight"		)
												lowerCAmelCase__    						=						state_dict.pop(F"sem_seg_head.predictor.transformer.decoder.layers.{idx}.multihead_attn.in_proj_bias"		)
												# next, add query, keys and values (in that order) to the state dict
												lowerCAmelCase__    						=						in_proj_weight[: hidden_size, :]
												lowerCAmelCase__    						=						in_proj_bias[:config.hidden_size]
												lowerCAmelCase__    						=						in_proj_weight[hidden_size : hidden_size * 2, :]
												lowerCAmelCase__    						=						in_proj_bias[hidden_size : hidden_size * 2]
												lowerCAmelCase__    						=						in_proj_weight[-hidden_size :, :]
												lowerCAmelCase__    						=						in_proj_bias[-hidden_size :]
						# fmt: on







def 	_UpperCamelCase   (    ):

						"""simple docstring"""



						lowerCAmelCase__    						=						'http://images.cocodataset.org/val2017/000000039769.jpg'
						lowerCAmelCase__    						=						Image.open(requests.get(UpperCamelCase_    ,       stream=UpperCamelCase_		).raw		)
						return im







@torch.no_grad()
def 	_UpperCamelCase   (    UpperCamelCase_       :					str    ,       UpperCamelCase_       :					str    ,       UpperCamelCase_       :					str    ,       UpperCamelCase_       :					bool = False		):

						"""simple docstring"""



						lowerCAmelCase__    						=						get_maskformer_config(UpperCamelCase_		)

						# load original state_dict
						with open(UpperCamelCase_    ,       'rb'		) as f:
												lowerCAmelCase__    						=						pickle.load(UpperCamelCase_		)
						lowerCAmelCase__    						=						data['model']

						# for name, param in state_dict.items():
						#     print(name, param.shape)

						# rename keys
						lowerCAmelCase__    						=						create_rename_keys(UpperCamelCase_		)
						for src, dest in rename_keys:
												rename_key(UpperCamelCase_    ,       UpperCamelCase_    ,       UpperCamelCase_		)
						read_in_swin_q_k_v(UpperCamelCase_    ,       config.backbone_config		)
						read_in_decoder_q_k_v(UpperCamelCase_    ,       UpperCamelCase_		)

						# update to torch tensors
						for key, value in state_dict.items():
												lowerCAmelCase__    						=						torch.from_numpy(UpperCamelCase_		)

						# load 🤗 model
						lowerCAmelCase__    						=						MaskFormerForInstanceSegmentation(UpperCamelCase_		)
						model.eval()

						for name, param in model.named_parameters():
												print(UpperCamelCase_    ,       param.shape		)

						lowerCAmelCase__						,       lowerCAmelCase__    						=						model.load_state_dict(UpperCamelCase_    ,       strict=UpperCamelCase_		)
						assert missing_keys == [
						    "model.pixel_level_module.encoder.model.layernorm.weight",
						    "model.pixel_level_module.encoder.model.layernorm.bias",
						]
						assert len(UpperCamelCase_		) == 0, F"Unexpected keys: {unexpected_keys}"

						# verify results
						lowerCAmelCase__    						=						prepare_img()
						if "vistas" in model_name:
												lowerCAmelCase__    						=						65
						elif "cityscapes" in model_name:
												lowerCAmelCase__    						=						6_5535
						else:
												lowerCAmelCase__    						=						255
						lowerCAmelCase__    						=						True if 'ade' in model_name else False
						lowerCAmelCase__    						=						MaskFormerImageProcessor(ignore_index=UpperCamelCase_    ,       reduce_labels=UpperCamelCase_		)

						lowerCAmelCase__    						=						image_processor(UpperCamelCase_    ,       return_tensors='pt'		)

						lowerCAmelCase__    						=						model(**UpperCamelCase_		)

						print('Logits:'    ,       outputs.class_queries_logits[0, :3, :3]		)

						if model_name == "maskformer-swin-tiny-ade":
												lowerCAmelCase__    						=						torch.tensor(
												    [[3.6353, -4.4770, -2.6065], [0.5081, -4.2394, -3.5343], [2.1909, -5.0353, -1.9323]]		)
						assert torch.allclose(outputs.class_queries_logits[0, :3, :3]    ,       UpperCamelCase_    ,       atol=1e-4		)
						print('Looks ok!'		)

						if pytorch_dump_folder_path is not None:
												print(F"Saving model and image processor to {pytorch_dump_folder_path}"		)
												Path(UpperCamelCase_		).mkdir(exist_ok=UpperCamelCase_		)
												model.save_pretrained(UpperCamelCase_		)
												image_processor.save_pretrained(UpperCamelCase_		)

						if push_to_hub:
												print('Pushing model and image processor to the hub...'		)
												model.push_to_hub(F"nielsr/{model_name}"		)
												image_processor.push_to_hub(F"nielsr/{model_name}"		)


if __name__ == "__main__":
					__snake_case    :    Dict         =     argparse.ArgumentParser()
					# Required parameters
					parser.add_argument(
					    """--model_name""",
					    default="""maskformer-swin-tiny-ade""",
					    type=str,
					    help=("""Name of the MaskFormer model you'd like to convert""",),
					)
					parser.add_argument(
					    """--checkpoint_path""",
					    default="""/Users/nielsrogge/Documents/MaskFormer_checkpoints/MaskFormer-Swin-tiny-ADE20k/model.pkl""",
					    type=str,
					    help="""Path to the original state dict (.pth file).""",
					)
					parser.add_argument(
					    """--pytorch_dump_folder_path""", default=None, type=str, help="""Path to the output PyTorch model directory."""
					)
					parser.add_argument(
					    """--push_to_hub""", action="""store_true""", help="""Whether or not to push the converted model to the 🤗 hub."""
					)

					__snake_case    :    Optional[Any]         =     parser.parse_args()
					convert_maskformer_checkpoint(
					    args.model_name, args.checkpoint_path, args.pytorch_dump_folder_path, args.push_to_hub
					)













__snake_case    :    Tuple         =     range(2, 20 + 1)
__snake_case    :    str         =     [10**k for k in range(ks[-1] + 1)]
__snake_case    :    dict[int, dict[int, list[list[int]]]]         =     {}







def 	_UpperCamelCase   (    UpperCamelCase_       :					Optional[int]    ,       UpperCamelCase_       :					List[Any]    ,       UpperCamelCase_       :					List[Any]    ,       UpperCamelCase_       :					Tuple		)  ->   List[Any]:

						"""simple docstring"""



						lowerCAmelCase__    						=						sum(a_i[j] for j in range(UpperCamelCase_    ,       len(UpperCamelCase_		)		)		)
						lowerCAmelCase__    						=						sum(a_i[j] * base[j] for j in range(min(len(UpperCamelCase_		)    ,       UpperCamelCase_		)		)		)

						lowerCAmelCase__						,       lowerCAmelCase__    						=						0, 0
						lowerCAmelCase__    						=						n - i

						lowerCAmelCase__    						=						memo.get(UpperCamelCase_		)

						if sub_memo is not None:
												lowerCAmelCase__    						=						sub_memo.get(UpperCamelCase_		)

												if jumps is not None and len(UpperCamelCase_		) > 0:
																		# find and make the largest jump without going over
																		lowerCAmelCase__    						=						-1
																		for _k in range(len(UpperCamelCase_		) - 1    ,       -1    ,       -1		):
																								if jumps[_k][2] <= k and jumps[_k][1] <= max_dn:
																														lowerCAmelCase__    						=						_k
																														break

																		if max_jump >= 0:
																								lowerCAmelCase__						,       lowerCAmelCase__						,       lowerCAmelCase__    						=						jumps[max_jump]
																								# since the difference between jumps is cached, add c
																								lowerCAmelCase__    						=						diff + c
																								for j in range(min(UpperCamelCase_    ,       len(UpperCamelCase_		)		)		):
																														lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
																								if new_c > 0:
																														add(UpperCamelCase_    ,       UpperCamelCase_    ,       UpperCamelCase_		)

												else:
																		lowerCAmelCase__    						=						[]
						else:
												lowerCAmelCase__    						=						{c: []}
												lowerCAmelCase__    						=						sub_memo

						if dn >= max_dn or c + diff >= base[k]:
												return diff, dn

						if k > ks[0]:
												while True:
																		# keep doing smaller jumps
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						next_term(UpperCamelCase_    ,       k - 1    ,       i + dn    ,       UpperCamelCase_		)
																		diff += _diff
																		dn += terms_jumped

																		if dn >= max_dn or c + diff >= base[k]:
																								break
						else:
												# would be too small a jump, just compute sequential terms instead
												lowerCAmelCase__						,       lowerCAmelCase__    						=						compute(UpperCamelCase_    ,       UpperCamelCase_    ,       i + dn    ,       UpperCamelCase_		)
												diff += _diff
												dn += terms_jumped

						lowerCAmelCase__    						=						sub_memo[c]

						# keep jumps sorted by # of terms skipped
						lowerCAmelCase__    						=						0
						while j < len(UpperCamelCase_		):
												if jumps[j][1] > dn:
																		break
												j += 1

						# cache the jump for this value digitsum(b) and c
						sub_memo[c].insert(UpperCamelCase_    ,       (diff, dn, k)		)
						return (diff, dn)







def 	_UpperCamelCase   (    UpperCamelCase_       :					Tuple    ,       UpperCamelCase_       :					List[str]    ,       UpperCamelCase_       :					int    ,       UpperCamelCase_       :					Tuple		)  ->   List[str]:

						"""simple docstring"""



						if i >= n:
												return 0, i
						if k > len(UpperCamelCase_		):
												a_i.extend([0 for _ in range(k - len(UpperCamelCase_		)		)]		)

						# note: a_i -> b * 10^k + c
						# ds_b -> digitsum(b)
						# ds_c -> digitsum(c)
						lowerCAmelCase__    						=						i
						lowerCAmelCase__						,       lowerCAmelCase__						,       lowerCAmelCase__    						=						0, 0, 0
						for j in range(len(UpperCamelCase_		)		):
												if j >= k:
																		ds_b += a_i[j]
												else:
																		ds_c += a_i[j]

						while i < n:
												i += 1
												lowerCAmelCase__    						=						ds_c + ds_b
												diff += addend
												lowerCAmelCase__    						=						0
												for j in range(UpperCamelCase_		):
																		lowerCAmelCase__    						=						a_i[j] + addend
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)

																		ds_c += a_i[j]

												if addend > 0:
																		break

						if addend > 0:
												add(UpperCamelCase_    ,       UpperCamelCase_    ,       UpperCamelCase_		)
						return diff, i - start_i







def 	_UpperCamelCase   (    UpperCamelCase_       :					Tuple    ,       UpperCamelCase_       :					Optional[int]    ,       UpperCamelCase_       :					List[str]		)  ->   List[str]:

						"""simple docstring"""



						for j in range(UpperCamelCase_    ,       len(UpperCamelCase_		)		):
												lowerCAmelCase__    						=						digits[j] + addend
												if s >= 10:
																		lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
																		lowerCAmelCase__    						=						addend // 10 + quotient
												else:
																		lowerCAmelCase__    						=						s
																		lowerCAmelCase__    						=						addend // 10

												if addend == 0:
																		break

						while addend > 0:
												lowerCAmelCase__						,       lowerCAmelCase__    						=						divmod(UpperCamelCase_    ,       10		)
												digits.append(UpperCamelCase_		)







def 	_UpperCamelCase   (    UpperCamelCase_       :					int = 10**15		)  ->   int:

						"""simple docstring"""



						lowerCAmelCase__    						=						[1]
						lowerCAmelCase__    						=						1
						lowerCAmelCase__    						=						0
						while True:
												lowerCAmelCase__						,       lowerCAmelCase__    						=						next_term(UpperCamelCase_    ,       20    ,       i + dn    ,       UpperCamelCase_		)
												dn += terms_jumped
												if dn == n - i:
																		break

						lowerCAmelCase__    						=						0
						for j in range(len(UpperCamelCase_		)		):
												a_n += digits[j] * 10**j
						return a_n


if __name__ == "__main__":
					print(f'{solution() = }')





