





import colorsys
import io

import cva
import matplotlib as mpl
import matplotlib.colors as mplc
import matplotlib.figure as mplfigure
import numpy as np
import torch
from matplotlib.backends.backend_agg import FigureCanvasAgg

from utils import img_tensorize


__lowerCAmelCase     =			1_000




class   _UpperCAmelCase	:




					def __init__(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase=1.2    ,      __lowerCAmelCase="g"    ,      __lowerCAmelCase=0.5    ,      __lowerCAmelCase="-"    ,      __lowerCAmelCase="test_out.jpg"    ,      __lowerCAmelCase=True    ,      __lowerCAmelCase=False    ,      __lowerCAmelCase=None    ,      __lowerCAmelCase=None    ,      __lowerCAmelCase=0.7    ,      )						->  List[str]:
							if isinstance(_snake_case    ,      torch.Tensor       ):
									UpperCamelCase__         =	img.numpy().astype("""np.uint8"""       )
							if isinstance(_snake_case    ,      _snake_case       ):
									UpperCamelCase__         =	img_tensorize(_snake_case       )
							assert isinstance(_snake_case    ,      np.ndarray       )

							UpperCamelCase__         =	img.shape[1], img.shape[0]
							UpperCamelCase__         =	mplfigure.Figure(frameon=_snake_case       )
							UpperCamelCase__         =	fig.get_dpi()
							UpperCamelCase__         =	(width * scale + 1E-2) / dpi
							UpperCamelCase__         =	(height * scale + 1E-2) / dpi
							fig.set_size_inches(_snake_case    ,      _snake_case       )
							UpperCamelCase__         =	fig.add_axes([0.0, 0.0, 1.0, 1.0]       )
							ax.axis("""off"""       )
							ax.set_xlim(0.0    ,      _snake_case       )
							ax.set_ylim(_snake_case       )

							UpperCamelCase__         =	saveas
							UpperCamelCase__         =	rgb
							UpperCamelCase__         =	pynb
							UpperCamelCase__         =	img
							UpperCamelCase__         =	edgecolor
							UpperCamelCase__         =	0.5
							UpperCamelCase__         =	linestyle
							UpperCamelCase__         =	int(np.sqrt(min(_snake_case    ,      _snake_case       )       ) * scale // 3       )
							UpperCamelCase__         =	width
							UpperCamelCase__         =	height
							UpperCamelCase__         =	scale
							UpperCamelCase__         =	fig
							UpperCamelCase__         =	ax
							UpperCamelCase__         =	pad
							UpperCamelCase__         =	idaobj
							UpperCamelCase__         =	idaattr
							UpperCamelCase__         =	FigureCanvasAgg(_snake_case       )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase=None       )						->  List[str]:
							if color is None:
									UpperCamelCase__         =	self.edgecolor
							(UpperCamelCase__)         =	box
							UpperCamelCase__         =	xa - xa
							UpperCamelCase__         =	ya - ya
							self.ax.add_patch(
							    mpl.patches.Rectangle(
							        (xa, ya)    ,      _snake_case    ,      _snake_case    ,      fill=_snake_case    ,      edgecolor=_snake_case    ,      linewidth=self.font_size // 3    ,      alpha=self.alpha    ,      linestyle=self.linestyle    ,      )       )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase=None    ,      __lowerCAmelCase=None    ,      __lowerCAmelCase=None    ,      __lowerCAmelCase=None       )						->  List[Any]:
							if len(boxes.shape       ) > 2:
									UpperCamelCase__         =	boxes[0]
							if len(obj_ids.shape       ) > 1:
									UpperCamelCase__         =	obj_ids[0]
							if len(obj_scores.shape       ) > 1:
									UpperCamelCase__         =	obj_scores[0]
							if len(attr_ids.shape       ) > 1:
									UpperCamelCase__         =	attr_ids[0]
							if len(attr_scores.shape       ) > 1:
									UpperCamelCase__         =	attr_scores[0]
							if isinstance(_snake_case    ,      torch.Tensor       ):
									UpperCamelCase__         =	boxes.numpy()
							if isinstance(_snake_case    ,      _snake_case       ):
									UpperCamelCase__         =	np.array(_snake_case       )
							assert isinstance(_snake_case    ,      np.ndarray       )
							UpperCamelCase__         =	np.prod(boxes[:, 2:] - boxes[:, :2]    ,      axis=1       )
							UpperCamelCase__         =	np.argsort(-areas       ).tolist()
							UpperCamelCase__         =	boxes[sorted_idxs] if boxes is not None else None
							UpperCamelCase__         =	obj_ids[sorted_idxs] if obj_ids is not None else None
							UpperCamelCase__         =	obj_scores[sorted_idxs] if obj_scores is not None else None
							UpperCamelCase__         =	attr_ids[sorted_idxs] if attr_ids is not None else None
							UpperCamelCase__         =	attr_scores[sorted_idxs] if attr_scores is not None else None

							UpperCamelCase__         =	[self._random_color(maximum=1       ) for _ in range(len(_snake_case       )       )]
							UpperCamelCase__         =	[assigned_colors[idx] for idx in sorted_idxs]
							if obj_ids is not None:
									UpperCamelCase__         =	self._create_text_labels_attr(_snake_case    ,      _snake_case    ,      _snake_case    ,      _snake_case       )
									for i in range(len(_snake_case       )       ):
											UpperCamelCase__         =	assigned_colors[i]
											self.add_box(boxes[i]    ,      _snake_case       )
											self.draw_labels(labels[i]    ,      boxes[i]    ,      _snake_case       )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )						->  Union[str, Any]:
							UpperCamelCase__         =	box
							UpperCamelCase__         =	(xa, ya)
							UpperCamelCase__         =	(ya - ya) * (xa - xa)
							UpperCamelCase__         =	_SMALL_OBJ * self.scale
							if instance_area < small or ya - ya < 40 * self.scale:
									if ya >= self.height - 5:
											UpperCamelCase__         =	(xa, ya)
									else:
											UpperCamelCase__         =	(xa, ya)

							UpperCamelCase__         =	(ya - ya) / np.sqrt(self.height * self.width       )
							UpperCamelCase__         =	self._change_color_brightness(_snake_case    ,      brightness_factor=0.7       )
							UpperCamelCase__         =	np.clip((height_ratio - 0.0_2) / 0.0_8 + 1    ,      1.2    ,      2       )
							font_size *= 0.7_5 * self.font_size

							self.draw_text(
							    text=_snake_case    ,      position=_snake_case    ,      color=_snake_case    ,      )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase="g"    ,      __lowerCAmelCase="left"    ,      )						->  str:
							UpperCamelCase__         =	0
							UpperCamelCase__         =	self.font_size
							UpperCamelCase__         =	np.maximum(list(mplc.to_rgb(_snake_case       )       )    ,      0.2       )
							UpperCamelCase__         =	max(0.8    ,      np.max(_snake_case       )       )
							UpperCamelCase__         =	{
							    '''facecolor''': '''black''',
							    '''alpha''': self.alpha,
							    '''pad''': self.pad,
							    '''edgecolor''': '''none''',
							}
							UpperCamelCase__         =	position
							self.ax.text(
							    _snake_case    ,      _snake_case    ,      _snake_case    ,      size=font_size * self.scale    ,      family="""sans-serif"""    ,      bbox=_snake_case    ,      verticalalignment="""top"""    ,      horizontalalignment=_snake_case    ,      color=_snake_case    ,      zorder=10    ,      rotation=_snake_case    ,      )




					def 	snake_case_		(						self    ,      __lowerCAmelCase=None       )						->  Dict:
							if saveas is None:
									UpperCamelCase__         =	self.saveas
							if saveas.lower().endswith(""".jpg"""       ) or saveas.lower().endswith(""".png"""       ):
									cva.imwrite(
									    _snake_case    ,      self._get_buffer()[:, :, ::-1]    ,      )
							else:
									self.fig.savefig(_snake_case       )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )						->  Optional[int]:
							UpperCamelCase__         =	[self.idaobj[i] for i in classes]
							UpperCamelCase__         =	[self.idaattr[i] for i in attr_classes]
							UpperCamelCase__         =	[
							    F"""{label} {score:.2f} {attr} {attr_score:.2f}"""
							    for label, score, attr, attr_score in zip(_snake_case    ,      _snake_case    ,      _snake_case    ,      _snake_case       )
							]
							return labels




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )						->  int:
							UpperCamelCase__         =	[self.idaobj[i] for i in classes]
							if scores is not None:
									if labels is None:
											UpperCamelCase__         =	['''{:.0f}%'''.format(s * 100       ) for s in scores]
									else:
											UpperCamelCase__         =	['''{} {:.0f}%'''.format(_snake_case    ,      s * 100       ) for li, s in zip(_snake_case    ,      _snake_case       )]
							return labels




					def 	snake_case_		(						self    ,      __lowerCAmelCase=255       )						->  Optional[int]:
							UpperCamelCase__         =	np.random.randint(0    ,      len(_COLORS       )       )
							UpperCamelCase__         =	_COLORS[idx] * maximum
							if not self.rgb:
									UpperCamelCase__         =	ret[::-1]
							return ret




					def 	snake_case_		(						self       )						->  Optional[Any]:
							if not self.pynb:
									UpperCamelCase__         =	self.canvas.print_to_buffer()
									if (width, height) != (self.width, self.height):
											UpperCamelCase__         =	cva.resize(self.img    ,      (width, height)       )
									else:
											UpperCamelCase__         =	self.img
							else:
									UpperCamelCase__         =	io.BytesIO()  # works for cairo backend
									self.canvas.print_rgba(_snake_case       )
									UpperCamelCase__         =	self.width, self.height
									UpperCamelCase__         =	buf.getvalue()
									UpperCamelCase__         =	self.img

							UpperCamelCase__         =	np.frombuffer(_snake_case    ,      dtype="""uint8"""       )
							UpperCamelCase__         =	buffer.reshape(_snake_case    ,      _snake_case    ,      4       )
							UpperCamelCase__         =	np.split(_snake_case    ,      [3]    ,      axis=2       )

							try:
									import numexpr as ne  # fuse them with numexpr

									UpperCamelCase__         =	ne.evaluate("""img * (1 - alpha / 255.0) + rgb * (alpha / 255.0)"""       )
							except ImportError:
									UpperCamelCase__         =	alpha.astype("""float32"""       ) / 2_5_5.0
									UpperCamelCase__         =	img * (1 - alpha) + rgb * alpha

							return visualized_image.astype("""uint8"""       )




					def 	snake_case_		(						self    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )						->  Optional[Any]:
							assert brightness_factor >= -1.0 and brightness_factor <= 1.0
							UpperCamelCase__         =	mplc.to_rgb(_snake_case       )
							UpperCamelCase__         =	colorsys.rgb_to_hls(*mplc.to_rgb(_snake_case       )       )
							UpperCamelCase__         =	polygon_color[1] + (brightness_factor * polygon_color[1])
							UpperCamelCase__         =	0.0 if modified_lightness < 0.0 else modified_lightness
							UpperCamelCase__         =	1.0 if modified_lightness > 1.0 else modified_lightness
							UpperCamelCase__         =	colorsys.hls_to_rgb(polygon_color[0]    ,      _snake_case    ,      polygon_color[2]       )
							return modified_color



__lowerCAmelCase     =			(
    np.array(
        [
            0.000,
            0.447,
            0.741,
            0.850,
            0.325,
            0.098,
            0.929,
            0.694,
            0.125,
            0.494,
            0.184,
            0.556,
            0.466,
            0.674,
            0.188,
            0.301,
            0.745,
            0.933,
            0.635,
            0.078,
            0.184,
            0.300,
            0.300,
            0.300,
            0.600,
            0.600,
            0.600,
            1.000,
            0.000,
            0.000,
            1.000,
            0.500,
            0.000,
            0.749,
            0.749,
            0.000,
            0.000,
            1.000,
            0.000,
            0.000,
            0.000,
            1.000,
            0.667,
            0.000,
            1.000,
            0.333,
            0.333,
            0.000,
            0.333,
            0.667,
            0.000,
            0.333,
            1.000,
            0.000,
            0.667,
            0.333,
            0.000,
            0.667,
            0.667,
            0.000,
            0.667,
            1.000,
            0.000,
            1.000,
            0.333,
            0.000,
            1.000,
            0.667,
            0.000,
            1.000,
            1.000,
            0.000,
            0.000,
            0.333,
            0.500,
            0.000,
            0.667,
            0.500,
            0.000,
            1.000,
            0.500,
            0.333,
            0.000,
            0.500,
            0.333,
            0.333,
            0.500,
            0.333,
            0.667,
            0.500,
            0.333,
            1.000,
            0.500,
            0.667,
            0.000,
            0.500,
            0.667,
            0.333,
            0.500,
            0.667,
            0.667,
            0.500,
            0.667,
            1.000,
            0.500,
            1.000,
            0.000,
            0.500,
            1.000,
            0.333,
            0.500,
            1.000,
            0.667,
            0.500,
            1.000,
            1.000,
            0.500,
            0.000,
            0.333,
            1.000,
            0.000,
            0.667,
            1.000,
            0.000,
            1.000,
            1.000,
            0.333,
            0.000,
            1.000,
            0.333,
            0.333,
            1.000,
            0.333,
            0.667,
            1.000,
            0.333,
            1.000,
            1.000,
            0.667,
            0.000,
            1.000,
            0.667,
            0.333,
            1.000,
            0.667,
            0.667,
            1.000,
            0.667,
            1.000,
            1.000,
            1.000,
            0.000,
            1.000,
            1.000,
            0.333,
            1.000,
            1.000,
            0.667,
            1.000,
            0.333,
            0.000,
            0.000,
            0.500,
            0.000,
            0.000,
            0.667,
            0.000,
            0.000,
            0.833,
            0.000,
            0.000,
            1.000,
            0.000,
            0.000,
            0.000,
            0.167,
            0.000,
            0.000,
            0.333,
            0.000,
            0.000,
            0.500,
            0.000,
            0.000,
            0.667,
            0.000,
            0.000,
            0.833,
            0.000,
            0.000,
            1.000,
            0.000,
            0.000,
            0.000,
            0.167,
            0.000,
            0.000,
            0.333,
            0.000,
            0.000,
            0.500,
            0.000,
            0.000,
            0.667,
            0.000,
            0.000,
            0.833,
            0.000,
            0.000,
            1.000,
            0.000,
            0.000,
            0.000,
            0.143,
            0.143,
            0.143,
            0.857,
            0.857,
            0.857,
            1.000,
            1.000,
            1.000,
        ]
    )
    .astype(np.floataa)
    .reshape(-1, 3)
)












def     a						(      _lowercase   :     int ,						_lowercase   :     int       )     ->int:
		UpperCamelCase__         =	1.0
		for i in range(1 ,						r + 1       ):
				ret *= (n + 1 - i) / i
		return round(_lowercase       )

def     a						(      _lowercase   :     int       )     ->int:
		return choose(8 + n ,						_lowercase       ) + choose(9 + n ,						_lowercase       ) - 1_0

def     a						(      _lowercase   :     int       )     ->int:
		return sum(non_bouncy_exact(_lowercase       ) for i in range(1 ,						n + 1       )       )

def     a						(      _lowercase   :     int = 1_0_0       )     ->int:
		return non_bouncy_upto(_lowercase       )


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





