





'''simple docstring'''




import itertools
from dataclasses import dataclass
from typing import List, Optional

import pyarrow as pa
import pyarrow.parquet as pq

import datasets
from datasets.table import table_cast


__UpperCAmelCase            =       datasets.utils.logging.get_logger(__name__)




@dataclass
class      UpperCamelCase__					(					datasets.BuilderConfig			):




					"""simple docstring"""
					SCREAMING_SNAKE_CASE__				=	1_0000
					SCREAMING_SNAKE_CASE__				=	None
					SCREAMING_SNAKE_CASE__				=	None







class      UpperCamelCase__					(					datasets.ArrowBasedBuilder			):




					"""simple docstring"""
					SCREAMING_SNAKE_CASE__				=	ParquetConfig


					def lowerCamelCase_			(						self				:			int						):

							'''simple docstring'''



							return datasets.DatasetInfo(features=self.config.features						)


					def lowerCamelCase_			(						self				:			Dict      ,						lowerCamelCase_				:			List[str]						):

							'''simple docstring'''



							if not self.config.data_files:
									raise ValueError(f'''At least one data file must be specified, but got data_files={self.config.data_files}'''						)
							SCREAMING_SNAKE_CASE :				Tuple		=			dl_manager.download_and_extract(self.config.data_files						)
							if isinstance(lowerCamelCase_      ,						(str, list, tuple)						):
									SCREAMING_SNAKE_CASE :				str		=			data_files
									if isinstance(lowerCamelCase_      ,						lowerCamelCase_						):
											SCREAMING_SNAKE_CASE :				Dict		=			[files]
									# Use `dl_manager.iter_files` to skip hidden files in an extracted archive
									SCREAMING_SNAKE_CASE :				Union[str, Any]		=			[dl_manager.iter_files(lowerCamelCase_						) for file in files]
									return [datasets.SplitGenerator(name=datasets.Split.TRAIN      ,						gen_kwargs={"""files""": files}						)]
							SCREAMING_SNAKE_CASE :				int		=			[]
							for split_name, files in data_files.items():
									if isinstance(lowerCamelCase_      ,						lowerCamelCase_						):
											SCREAMING_SNAKE_CASE :				List[str]		=			[files]
									# Use `dl_manager.iter_files` to skip hidden files in an extracted archive
									SCREAMING_SNAKE_CASE :				int		=			[dl_manager.iter_files(lowerCamelCase_						) for file in files]
									# Infer features is they are stoed in the arrow schema
									if self.info.features is None:
											for file in itertools.chain.from_iterable(lowerCamelCase_						):
													with open(lowerCamelCase_      ,						"""rb"""						) as f:
															SCREAMING_SNAKE_CASE :				Optional[Any]		=			datasets.Features.from_arrow_schema(pq.read_schema(lowerCamelCase_						)						)
													break
									splits.append(datasets.SplitGenerator(name=lowerCamelCase_      ,						gen_kwargs={"""files""": files}						)						)
							return splits


					def lowerCamelCase_			(						self				:			List[str]      ,						lowerCamelCase_				:			pa.Table						):

							'''simple docstring'''



							if self.info.features is not None:
									# more expensive cast to support nested features with keys in a different order
									# allows str <-> int/float or str to Audio for example
									SCREAMING_SNAKE_CASE :				Union[str, Any]		=			table_cast(lowerCamelCase_      ,						self.info.features.arrow_schema						)
							return pa_table



					def lowerCamelCase_			(						self				:			Union[str, Any]      ,						lowerCamelCase_				:			List[Any]						):

							'''simple docstring'''



							SCREAMING_SNAKE_CASE :				List[str]		=			self.info.features.arrow_schema if self.info.features is not None else None
							if self.info.features is not None and self.config.columns is not None:
									if sorted(field.name for field in schema						) != sorted(self.config.columns						):
											raise ValueError(
											    f'''Tried to load parquet data with columns \'{self.config.columns}\' with mismatching features \'{self.info.features}\''''						)
							for file_idx, file in enumerate(itertools.chain.from_iterable(lowerCamelCase_						)						):
									with open(lowerCamelCase_      ,						"""rb"""						) as f:
											SCREAMING_SNAKE_CASE :				List[Any]		=			pq.ParquetFile(lowerCamelCase_						)
											try:
													for batch_idx, record_batch in enumerate(
													    parquet_file.iter_batches(batch_size=self.config.batch_size      ,						columns=self.config.columns						)						):
															SCREAMING_SNAKE_CASE :				str		=			pa.Table.from_batches([record_batch]						)
															# Uncomment for debugging (will print the Arrow table size and elements)
															# logger.warning(f"pa_table: {pa_table} num rows: {pa_table.num_rows}")
															# logger.warning('\n'.join(str(pa_table.slice(i, 1).to_pydict()) for i in range(pa_table.num_rows)))
															yield f'''{file_idx}_{batch_idx}''', self._cast_table(lowerCamelCase_						)
											except ValueError as e:
													logger.error(f'''Failed to read file \'{file}\' with error {type(lowerCamelCase_						)}: {e}'''						)
													raise










'''simple docstring'''




def 		__A		(  lowerCamelCase_			,			lowerCamelCase_	):


		"""simple docstring"""



		SCREAMING_SNAKE_CASE :				str		=			1  # To kept the Calculated Value
		# Since C(n, k) = C(n, n-k)
		if k > (n - k):
				SCREAMING_SNAKE_CASE :				Dict		=			n - k
		# Calculate C(n,k)
		for i in range(lowerCamelCase_	):
				result *= n - i
				result //= i + 1
		return result



def 		__A		(  lowerCamelCase_	):


		"""simple docstring"""



		return binomial_coefficient(2 * node_count			,			lowerCamelCase_	) // (node_count + 1)



def 		__A		(  lowerCamelCase_	):


		"""simple docstring"""



		if n < 0:
				raise ValueError("""factorial() not defined for negative values"""	)
		SCREAMING_SNAKE_CASE :				Dict		=			1
		for i in range(1			,			n + 1	):
				result *= i
		return result



def 		__A		(  lowerCamelCase_	):


		"""simple docstring"""



		return catalan_number(lowerCamelCase_	) * factorial(lowerCamelCase_	)


if __name__ == "__main__":
							__UpperCAmelCase            =       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.'''
							)



