



"""simple docstring"""





import os
import sys
import warnings
from dataclasses import dataclass, field
from io import BytesIO
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Union

import numpy as np
import pyarrow as pa

from .. import config
from ..download.streaming_download_manager import xopen
from ..table import array_cast
from ..utils.file_utils import is_local_path
from ..utils.py_utils import first_non_null_value, no_op_if_value_is_null, string_to_dict


if TYPE_CHECKING:
					import PIL.Image

					from .features import FeatureType


__lowerCAmelCase       :					int      					=					None
__lowerCAmelCase       :					str      					=					'''<''' if sys.byteorder == '''little''' else '''>'''
# Origin: https://github.com/python-pillow/Pillow/blob/698951e19e19972aeed56df686868f1329981c12/src/PIL/Image.py#L3126 minus "|i1" which values are not preserved correctly when saving and loading an image
__lowerCAmelCase       :					Dict      					=					[
    np.dtype('''|b1'''),
    np.dtype('''|u1'''),
    np.dtype('''<u2'''),
    np.dtype('''>u2'''),
    np.dtype('''<i2'''),
    np.dtype('''>i2'''),
    np.dtype('''<u4'''),
    np.dtype('''>u4'''),
    np.dtype('''<i4'''),
    np.dtype('''>i4'''),
    np.dtype('''<f4'''),
    np.dtype('''>f4'''),
    np.dtype('''<f8'''),
    np.dtype('''>f8'''),
]



@dataclass
class    _lowerCAmelCase    :





		"""simple docstring"""






		_lowerCamelCase			  =       True
		_lowerCamelCase			  =       None
		# Automatically constructed
		_lowerCamelCase			  =       '''PIL.Image.Image'''
		_lowerCamelCase			  =       pa.struct({'''bytes''': pa.binary(), '''path''': pa.string()}		)
		_lowerCamelCase			  =       field(default='''Image'''  ,				init=__lowerCamelCase  ,				repr=__lowerCamelCase		)





		def __call__(					self   ) ->						Optional[Any]:







								'''simple docstring'''

								return self.pa_type





		def    UpperCAmelCase__							(					self							,    _lowercase   ) ->						str:







								'''simple docstring'''

								if config.PIL_AVAILABLE:
														import PIL.Image
								else:
														raise ImportError("""To support encoding images, please install \'Pillow\'."""   )

								if isinstance(UpperCAmelCase_							,    UpperCAmelCase_   ):
														snake_case_   : int						=			np.array(UpperCAmelCase_   )

								if isinstance(UpperCAmelCase_							,    UpperCAmelCase_   ):
														return {"path": value, "bytes": None}
								elif isinstance(UpperCAmelCase_							,    UpperCAmelCase_   ):
														return {"path": None, "bytes": value}
								elif isinstance(UpperCAmelCase_							,    np.ndarray   ):
														# convert the image array to PNG/TIFF bytes
														return encode_np_array(UpperCAmelCase_   )
								elif isinstance(UpperCAmelCase_							,    PIL.Image.Image   ):
														# convert the PIL image to bytes (default format is PNG/TIFF)
														return encode_pil_image(UpperCAmelCase_   )
								elif value.get("""path"""   ) is not None and os.path.isfile(value["""path"""]   ):
														# we set "bytes": None to not duplicate the data if they're already available locally
														return {"bytes": None, "path": value.get("""path"""   )}
								elif value.get("""bytes"""   ) is not None or value.get("""path"""   ) is not None:
														# store the image bytes, and path is used to infer the image format using the file extension
														return {"bytes": value.get("""bytes"""   ), "path": value.get("""path"""   )}
								else:
														raise ValueError(
														    f'An image sample should have one of \'path\' or \'bytes\' but they are missing or None in {value}.'   )





		def    UpperCAmelCase__							(					self							,    _lowercase							,    _lowercase=None   ) ->						str:







								'''simple docstring'''

								if not self.decode:
														raise RuntimeError("""Decoding is disabled for this feature. Please use Image(decode=True) instead."""   )

								if config.PIL_AVAILABLE:
														import PIL.Image
								else:
														raise ImportError("""To support decoding images, please install \'Pillow\'."""   )

								if token_per_repo_id is None:
														snake_case_   : int						=			{}

								snake_case_   : int						=			value['path'], value['bytes']
								if bytes_ is None:
														if path is None:
																				raise ValueError(f'An image should have one of \'path\' or \'bytes\' but both are None in {value}.'   )
														else:
																				if is_local_path(UpperCAmelCase_   ):
																										snake_case_   : int						=			PIL.Image.open(UpperCAmelCase_   )
																				else:
																										snake_case_   : str						=			path.split("""::"""   )[-1]
																										try:
																																snake_case_   : Union[str, Any]						=			string_to_dict(UpperCAmelCase_							,    config.HUB_DATASETS_URL   )['repo_id']
																																snake_case_   : Optional[Any]						=			token_per_repo_id.get(UpperCAmelCase_   )
																										except ValueError:
																																snake_case_   : Any						=			None
																										with xopen(UpperCAmelCase_							,    """rb"""							,    use_auth_token=UpperCAmelCase_   ) as f:
																																snake_case_   : Optional[int]						=			BytesIO(f.read()   )
																										snake_case_   : Tuple						=			PIL.Image.open(bytes_   )
								else:
														snake_case_   : List[Any]						=			PIL.Image.open(BytesIO(bytes_   )   )
								image.load()  # to avoid "Too many open files" errors
								return image





		def    UpperCAmelCase__							(					self   ) ->						List[Any]:







								'''simple docstring'''

								from .features import Value

								return (
								    self
								    if self.decode
								    else {
								        "bytes": Value("""binary"""   ),
								        "path": Value("""string"""   ),
								    }
								)





		def    UpperCAmelCase__							(					self							,    _lowercase   ) ->						int:







								'''simple docstring'''

								if pa.types.is_string(storage.type   ):
														snake_case_   : Dict						=			pa.array([None] * len(UpperCAmelCase_   )							,    type=pa.binary()   )
														snake_case_   : Union[str, Any]						=			pa.StructArray.from_arrays([bytes_array, storage]							,    ["""bytes""", """path"""]							,    mask=storage.is_null()   )
								elif pa.types.is_binary(storage.type   ):
														snake_case_   : Tuple						=			pa.array([None] * len(UpperCAmelCase_   )							,    type=pa.string()   )
														snake_case_   : Optional[int]						=			pa.StructArray.from_arrays([storage, path_array]							,    ["""bytes""", """path"""]							,    mask=storage.is_null()   )
								elif pa.types.is_struct(storage.type   ):
														if storage.type.get_field_index("""bytes"""   ) >= 0:
																				snake_case_   : Tuple						=			storage.field("""bytes"""   )
														else:
																				snake_case_   : Tuple						=			pa.array([None] * len(UpperCAmelCase_   )							,    type=pa.binary()   )
														if storage.type.get_field_index("""path"""   ) >= 0:
																				snake_case_   : int						=			storage.field("""path"""   )
														else:
																				snake_case_   : List[str]						=			pa.array([None] * len(UpperCAmelCase_   )							,    type=pa.string()   )
														snake_case_   : Dict						=			pa.StructArray.from_arrays([bytes_array, path_array]							,    ["""bytes""", """path"""]							,    mask=storage.is_null()   )
								elif pa.types.is_list(storage.type   ):
														snake_case_   : Optional[Any]						=			pa.array(
														    [encode_np_array(np.array(UpperCAmelCase_   )   )["""bytes"""] if arr is not None else None for arr in storage.to_pylist()]							,    type=pa.binary()							,    )
														snake_case_   : Optional[Any]						=			pa.array([None] * len(UpperCAmelCase_   )							,    type=pa.string()   )
														snake_case_   : Optional[int]						=			pa.StructArray.from_arrays(
														    [bytes_array, path_array]							,    ["""bytes""", """path"""]							,    mask=bytes_array.is_null()   )
								return array_cast(UpperCAmelCase_							,    self.pa_type   )





		def    UpperCAmelCase__							(					self							,    _lowercase   ) ->						Tuple:







								'''simple docstring'''

								@no_op_if_value_is_null
								def path_to_bytes(_lowercase   ):
														with xopen(UpperCAmelCase_							,    """rb"""   ) as f:
																				snake_case_   : List[str]						=			f.read()
														return bytes_

								snake_case_   : Optional[Any]						=			pa.array(
								    [
								        (path_to_bytes(x["""path"""]   ) if x["""bytes"""] is None else x["""bytes"""]) if x is not None else None
								        for x in storage.to_pylist()
								    ]							,    type=pa.binary()							,    )
								snake_case_   : List[Any]						=			pa.array(
								    [os.path.basename(UpperCAmelCase_   ) if path is not None else None for path in storage.field("""path"""   ).to_pylist()]							,    type=pa.string()							,    )
								snake_case_   : str						=			pa.StructArray.from_arrays([bytes_array, path_array]							,    ["""bytes""", """path"""]							,    mask=bytes_array.is_null()   )
								return array_cast(UpperCAmelCase_							,    self.pa_type   )




def 	__lowerCAmelCase						(		):


						'''simple docstring'''






						if config.PIL_AVAILABLE:
												import PIL.Image
						else:
												raise ImportError("""To support encoding images, please install \'Pillow\'."""    )

						global _IMAGE_COMPRESSION_FORMATS
						if _IMAGE_COMPRESSION_FORMATS is None:
												PIL.Image.init()
												snake_case_   : Tuple						=			list(set(PIL.Image.OPEN.keys()    ) & set(PIL.Image.SAVE.keys()    )    )
						return _IMAGE_COMPRESSION_FORMATS
def 	__lowerCAmelCase						(		__UpperCamelCase      :			int    ):


						'''simple docstring'''






						snake_case_   : List[Any]						=			BytesIO()
						if image.format in list_image_compression_formats():
												snake_case_   : Dict						=			image.format
						else:
												snake_case_   : List[str]						=			'PNG' if image.mode in ['1', 'L', 'LA', 'RGB', 'RGBA'] else 'TIFF'
						image.save(lowerCamelCase_					, format=lowerCamelCase_    )
						return buffer.getvalue()
def 	__lowerCAmelCase						(		__UpperCamelCase      :			int    ):


						'''simple docstring'''






						if hasattr(lowerCamelCase_					, """filename"""    ) and image.filename != "":
												return {"path": image.filename, "bytes": None}
						else:
												return {"path": None, "bytes": image_to_bytes(lowerCamelCase_    )}
def 	__lowerCAmelCase						(		__UpperCamelCase      :			Any    ):


						'''simple docstring'''






						if config.PIL_AVAILABLE:
												import PIL.Image
						else:
												raise ImportError("""To support encoding images, please install \'Pillow\'."""    )

						snake_case_   : List[Any]						=			array.dtype
						snake_case_   : Union[str, Any]						=			dtype.byteorder if dtype.byteorder != '=' else _NATIVE_BYTEORDER
						snake_case_   : Optional[int]						=			dtype.kind
						snake_case_   : int						=			dtype.itemsize

						snake_case_   : List[str]						=			None

						# Multi-channel array case (only np.dtype("|u1") is allowed)
						if array.shape[2:]:
												snake_case_   : Union[str, Any]						=			np.dtype("""|u1"""    )
												if dtype_kind not in ["u", "i"]:
																		raise TypeError(
																		    F'Unsupported array dtype {dtype} for image encoding. Only {dest_dtype} is supported for multi-channel arrays.'    )
												if dtype is not dest_dtype:
																		warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\''    )
    # Exact match
						elif dtype in _VALID_IMAGE_ARRAY_DTPYES:
												snake_case_   : Union[str, Any]						=			dtype
						else:  # Downcast the type within the kind (np.can_cast(from_type, to_type, casting="same_kind") doesn't behave as expected, so do it manually)
												while dtype_itemsize >= 1:
																		snake_case_   : List[str]						=			dtype_byteorder + dtype_kind + str(lowerCamelCase_    )
																		snake_case_   : Any						=			np.dtype(lowerCamelCase_    )
																		if dest_dtype in _VALID_IMAGE_ARRAY_DTPYES:
																								warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\''    )
																								break
																		else:
																								dtype_itemsize //= 2

						if dest_dtype is None:
												raise TypeError(
												    F'Cannot convert dtype {dtype} to a valid image dtype. Valid image dtypes: {_VALID_IMAGE_ARRAY_DTPYES}'    )
						snake_case_   : Optional[int]						=			PIL.Image.fromarray(array.astype(lowerCamelCase_    )    )
						return {"path": None, "bytes": image_to_bytes(lowerCamelCase_    )}






def 	__lowerCAmelCase						(		__UpperCamelCase      :			Optional[Any]    ):


						'''simple docstring'''






						if config.PIL_AVAILABLE:
												import PIL.Image
						else:
												raise ImportError("""To support encoding images, please install \'Pillow\'."""    )

						if objs:
												snake_case_   : str						=			first_non_null_value(lowerCamelCase_    )
												if isinstance(lowerCamelCase_					, lowerCamelCase_    ):
																		return [{"path": obj, "bytes": None} if obj is not None else None for obj in objs]
												if isinstance(lowerCamelCase_					, np.ndarray    ):
																		snake_case_   : List[str]						=			no_op_if_value_is_null(lowerCamelCase_    )
																		return [obj_to_image_dict_func(lowerCamelCase_    ) for obj in objs]
												elif isinstance(lowerCamelCase_					, PIL.Image.Image    ):
																		snake_case_   : Union[str, Any]						=			no_op_if_value_is_null(lowerCamelCase_    )
																		return [obj_to_image_dict_func(lowerCamelCase_    ) for obj in objs]
												else:
																		return objs
						else:
												return objs






"""simple docstring"""





def 	__lowerCAmelCase						(		__UpperCamelCase      :			int					, __UpperCamelCase      :			int    ):


						'''simple docstring'''






						snake_case_   : Any						=			1  # To kept the Calculated Value
						# Since C(n, k) = C(n, n-k)
						if k > (n - k):
												snake_case_   : Optional[int]						=			n - k
						# Calculate C(n,k)
						for i in range(__UpperCamelCase    ):
												result *= n - i
												result //= i + 1
						return result
def 	__lowerCAmelCase						(		__UpperCamelCase      :			int    ):


						'''simple docstring'''






						return binomial_coefficient(2 * node_count					, __UpperCamelCase    ) // (node_count + 1)
def 	__lowerCAmelCase						(		__UpperCamelCase      :			int    ):


						'''simple docstring'''






						if n < 0:
												raise ValueError("""factorial() not defined for negative values"""    )
						snake_case_   : Optional[int]						=			1
						for i in range(1					, n + 1    ):
												result *= i
						return result
def 	__lowerCAmelCase						(		__UpperCamelCase      :			int    ):


						'''simple docstring'''






						return catalan_number(__UpperCamelCase    ) * factorial(__UpperCamelCase    )


if __name__ == "__main__":
					__lowerCAmelCase       :					Optional[Any]      					=					int(input('''Enter the number of nodes: ''').strip() or 0)
					if node_count <= 0:
										raise ValueError('''We need some nodes to work with.''')
					print(
					    F'''Given {node_count} nodes, there are {binary_tree_count(node_count)} '''
					    F'''binary trees and {catalan_number(node_count)} binary search trees.'''
					)

