
import enum
import inspect
from typing import Iterable, List, Optional, Tuple, Union







class 							UpperCAmelCase	(   enum.Enum					):
					a__: Tuple			  =				"""timm"""
					a__: Optional[int]			  =				"""transformers"""





def        lowerCamelCase_      (			UpperCAmelCase_							:				Optional[Iterable[str]]							,			UpperCAmelCase_							:				Optional[Iterable[int]]							,			UpperCAmelCase_							:				Optional[Iterable[str]]       ):
						if stage_names is None:
												raise ValueError('''Stage_names must be set for transformers backbones'''       )

						if out_features is not None:
												if not isinstance(UpperCAmelCase_							,			(list,)       ):
																		raise ValueError(f'''out_features must be a list {type(UpperCAmelCase_       )}'''       )
												if any(feat not in stage_names for feat in out_features       ):
																		raise ValueError(f'''out_features must be a subset of stage_names: {stage_names} got {out_features}'''       )

						if out_indices is not None:
												if not isinstance(UpperCAmelCase_							,			(list, tuple)       ):
																		raise ValueError(f'''out_indices must be a list or tuple, got {type(UpperCAmelCase_       )}'''       )
												if any(idx >= len(UpperCAmelCase_       ) for idx in out_indices       ):
																		raise ValueError('''out_indices must be valid indices for stage_names {stage_names}, got {out_indices}'''       )

						if out_features is not None and out_indices is not None:
												if len(UpperCAmelCase_       ) != len(UpperCAmelCase_       ):
																		raise ValueError('''out_features and out_indices should have the same length if both are set'''       )
												if out_features != [stage_names[idx] for idx in out_indices]:
																		raise ValueError('''out_features and out_indices should correspond to the same stages if both are set'''       )

def        lowerCamelCase_      (			UpperCAmelCase_							:				Optional[List[str]]							,			UpperCAmelCase_							:				Optional[Union[List[int], Tuple[int]]]							,			UpperCAmelCase_							:				List[str]							,			):
						if out_indices is None and out_features is None:
												lowercase       :    Any											=  [len(UpperCAmelCase_       ) - 1]
												lowercase       :    Tuple											=  [stage_names[-1]]
						elif out_indices is None and out_features is not None:
												lowercase       :    Optional[Any]											=  [stage_names.index(UpperCAmelCase_       ) for layer in out_features]
						elif out_features is None and out_indices is not None:
												lowercase       :    Any											=  [stage_names[idx] for idx in out_indices]
						return out_features, out_indices

def        lowerCamelCase_      (			UpperCAmelCase_							:				Optional[List[str]]							,			UpperCAmelCase_							:				Optional[Union[List[int], Tuple[int]]]							,			UpperCAmelCase_							:				List[str]							,			):
						verify_out_features_out_indices(out_features=UpperCAmelCase_							,			out_indices=UpperCAmelCase_							,			stage_names=UpperCAmelCase_       )
						lowercase				,				lowercase       :    Dict											=  _align_output_features_output_indices(
						    out_features=UpperCAmelCase_							,			out_indices=UpperCAmelCase_							,			stage_names=UpperCAmelCase_       )
						# Verify that the aligned out_features and out_indices are valid
						verify_out_features_out_indices(out_features=UpperCAmelCase_							,			out_indices=UpperCAmelCase_							,			stage_names=UpperCAmelCase_       )
						return output_features, output_indices







class 							UpperCAmelCase	:
					a__: Optional[BackboneType]			  =				None

					def        _lowerCAmelCase	(			self      :					Any ,      lowerCAmelCase      :					List[str]					):
											if getattr(self ,      '''_backbone''' ,      lowerCAmelCase					) is None:
																	raise ValueError('''self._backbone must be set before calling _init_timm_backbone'''					)

											# These will diagree with the defaults for the transformers models e.g. for resnet50
											# the transformer model has out_features = ['stem', 'stage1', 'stage2', 'stage3', 'stage4']
											# the timm model has out_features = ['act', 'layer1', 'layer2', 'layer3', 'layer4']
											lowercase       :    Tuple											=  [stage['''module'''] for stage in self._backbone.feature_info.info]
											lowercase       :    Union[str, Any]											=  [stage['''num_chs'''] for stage in self._backbone.feature_info.info]
											lowercase       :    List[Any]											=  self._backbone.feature_info.out_indices
											lowercase       :    Union[str, Any]											=  self._backbone.feature_info.module_name()

											# We verify the out indices and out features are valid
											verify_out_features_out_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=self.stage_names					)
											lowercase				,				lowercase       :    Dict											=  out_features, out_indices

					def        _lowerCAmelCase	(			self      :					int ,      lowerCAmelCase      :					List[str]					):
											lowercase       :    Dict											=  getattr(lowerCAmelCase ,      '''stage_names'''					)
											lowercase       :    Any											=  getattr(lowerCAmelCase ,      '''out_features''' ,      lowerCAmelCase					)
											lowercase       :    List[Any]											=  getattr(lowerCAmelCase ,      '''out_indices''' ,      lowerCAmelCase					)

											lowercase       :    Optional[Any]											=  stage_names
											lowercase				,				lowercase       :    Dict											=  get_aligned_output_features_output_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=lowerCAmelCase					)
											# Number of channels for each stage. This is set in the transformer backbone model init
											lowercase       :    int											=  None

					def        _lowerCAmelCase	(			self      :					str ,      lowerCAmelCase      :					Optional[int]					):
											lowercase       :    Any											=  config

											lowercase       :    str											=  getattr(lowerCAmelCase ,      '''use_timm_backbone''' ,      lowerCAmelCase					)
											lowercase       :    Dict											=  BackboneType.TIMM if self.use_timm_backbone else BackboneType.TRANSFORMERS

											if self.backbone_type == BackboneType.TIMM:
																	self._init_timm_backbone(lowerCAmelCase					)
											elif self.backbone_type == BackboneType.TRANSFORMERS:
																	self._init_transformers_backbone(lowerCAmelCase					)
											else:
																	raise ValueError(f'''backbone_type {self.backbone_type} not supported.'''					)

					@property
					def        _lowerCAmelCase	(			self      :					Any					):
											return self._out_features

					@out_features.setter
					def        _lowerCAmelCase	(			self      :					Optional[Any] ,      lowerCAmelCase      :					List[str]					):
											lowercase				,				lowercase       :    Optional[Any]											=  get_aligned_output_features_output_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=self.stage_names					)

					@property
					def        _lowerCAmelCase	(			self      :					Optional[int]					):
											return self._out_indices

					@out_indices.setter
					def        _lowerCAmelCase	(			self      :					List[Any] ,      lowerCAmelCase      :					Union[Tuple[int], List[int]]					):
											lowercase				,				lowercase       :    Optional[Any]											=  get_aligned_output_features_output_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=self.stage_names					)

					@property
					def        _lowerCAmelCase	(			self      :					List[str]					):
											# the current backbones will output the number of channels for each stage
											# even if that stage is not in the out_features list.
											return {stage: self.num_features[i] for i, stage in enumerate(self.stage_names					)}

					@property
					def        _lowerCAmelCase	(			self      :					List[Any]					):
											return [self.out_feature_channels[name] for name in self.out_features]

					def        _lowerCAmelCase	(			self      :					Any ,      *lowerCAmelCase      :					int ,      **lowerCAmelCase      :					str					):
											lowercase       :    Any											=  dict(inspect.signature(self.forward					).parameters					)
											lowercase       :    List[str]											=  {k: v for k, v in kwargs.items() if k in signature}
											return self(*lowerCAmelCase ,      **lowerCAmelCase					)

					def        _lowerCAmelCase	(			self      :					Dict ,      lowerCAmelCase      :					Union[str, Any] ,      lowerCAmelCase      :					Optional[bool] = None ,      lowerCAmelCase      :					Optional[bool] = None ,      lowerCAmelCase      :					Optional[bool] = None ,      ):
											raise NotImplementedError('''This method should be implemented by the derived class.'''					)




					def        _lowerCAmelCase	(			self      :					Optional[Any]					):
											lowercase       :    Tuple											=  super().to_dict()
											lowercase       :    Any											=  output.pop('''_out_features'''					)
											lowercase       :    List[str]											=  output.pop('''_out_indices'''					)
											return output







class 							UpperCAmelCase	:

					@property
					def        _lowerCAmelCase	(			self      :					int					):
											return self._out_features

					@out_features.setter
					def        _lowerCAmelCase	(			self      :					Tuple ,      lowerCAmelCase      :					List[str]					):
											lowercase				,				lowercase       :    List[Any]											=  get_aligned_output_features_output_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=self.stage_names					)

					@property
					def        _lowerCAmelCase	(			self      :					Optional[int]					):
											return self._out_indices

					@out_indices.setter
					def        _lowerCAmelCase	(			self      :					Dict ,      lowerCAmelCase      :					Union[Tuple[int], List[int]]					):
											lowercase				,				lowercase       :    str											=  get_aligned_output_features_output_indices(
											    out_features=lowerCAmelCase ,      out_indices=lowerCAmelCase ,      stage_names=self.stage_names					)




					def        _lowerCAmelCase	(			self      :					List[Any]					):
											lowercase       :    Tuple											=  super().to_dict()
											lowercase       :    Dict											=  output.pop('''_out_features'''					)
											lowercase       :    Dict											=  output.pop('''_out_indices'''					)
											return output




from itertools import combinations_with_replacement

def        lowerCamelCase_      (			UpperCAmelCase_							:				int = 1_00       ):
						lowercase       :    list[int]											=  [*list(range(1							,			21       )       ), 25]
						lowercase       :    list[int]											=  [2 * x for x in range(1							,			21       )] + [50]
						lowercase       :    list[int]											=  [3 * x for x in range(1							,			21       )]
						lowercase       :    list[int]											=  singles + doubles + triples + [0]

						lowercase       :    int											=  0
						lowercase       :    int
						lowercase       :    int
						lowercase       :    int
						lowercase       :    int

						for double in doubles:
												for throwa, throwa in combinations_with_replacement(UpperCAmelCase_							,			2       ):
																		lowercase       :    Union[str, Any]											=  double + throwa + throwa
																		if checkout_total < limit:
																								num_checkouts += 1

						return num_checkouts


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


