

from collections.abc import Iterable
from typing import Any







class 				lowercase       :




				def __init__(      self   ,     snake_case = None ):
											snake_case_           =					value
											snake_case_           =					None  # Added in order to delete a node easier
											snake_case_           =					None
											snake_case_           =					None




				def __repr__(      self ):
											from pprint import pformat

											if self.left is None and self.right is None:
																		return str(self.value )
											return pformat({F'''{self.value}''': (self.left, self.right)}   ,     indent=1 )







class 				lowercase       :




				def __init__(      self   ,     snake_case = None ):
											snake_case_           =					root




				def __str__(      self ):
											return str(self.root )




				def 					a							(      self   ,     snake_case   ,     snake_case ):
											if new_children is not None:  # reset its kids
																		snake_case_           =					node.parent
											if node.parent is not None:  # reset its parent
																		if self.is_right(snake_case ):  # If it is the right children
																									snake_case_           =					new_children
																		else:
																									snake_case_           =					new_children
											else:
																		snake_case_           =					new_children




				def 					a							(      self   ,     snake_case ):
											if node.parent and node.parent.right:
																		return node == node.parent.right
											return False




				def 					a							(      self ):
											return self.root is None




				def 					a							(      self   ,     snake_case ):
											snake_case_           =					Node(snake_case )  # create a new Node
											if self.empty():  # if Tree is empty
																		snake_case_           =					new_node  # set its root
											else:  # Tree is not empty
																		snake_case_           =					self.root  # from root
																		if parent_node is None:
																									return
																		while True:  # While we don't get to a leaf
																									if value < parent_node.value:  # We go left
																																if parent_node.left is None:
																																							snake_case_           =					new_node  # We insert the new node in a leaf
																																							break
																																else:
																																							snake_case_           =					parent_node.left
																									else:
																																if parent_node.right is None:
																																							snake_case_           =					new_node
																																							break
																																else:
																																							snake_case_           =					parent_node.right
																		snake_case_           =					parent_node




				def 					a							(      self   ,     *snake_case ):
											for value in values:
																		self.__insert(snake_case )




				def 					a							(      self   ,     snake_case ):
											if self.empty():
																		raise IndexError('Warning: Tree is empty! please use another.' )
											else:
																		snake_case_           =					self.root
																		# use lazy evaluation here to avoid NoneType Attribute error
																		while node is not None and node.value is not value:
																									snake_case_           =					node.left if value < node.value else node.right
																		return node




				def 					a							(      self   ,     snake_case = None ):
											if node is None:
																		if self.root is None:
																									return None
																		snake_case_           =					self.root

											if not self.empty():
																		while node.right is not None:
																									snake_case_           =					node.right
											return node




				def 					a							(      self   ,     snake_case = None ):
											if node is None:
																		snake_case_           =					self.root
											if self.root is None:
																		return None
											if not self.empty():
																		snake_case_           =					self.root
																		while node.left is not None:
																									snake_case_           =					node.left
											return node




				def 					a							(      self   ,     snake_case ):
											snake_case_           =					self.search(snake_case )  # Look for the node with that label
											if node is not None:
																		if node.left is None and node.right is None:  # If it has no children
																									self.__reassign_nodes(snake_case   ,     snake_case )
																		elif node.left is None:  # Has only right children
																									self.__reassign_nodes(snake_case   ,     node.right )
																		elif node.right is None:  # Has only left children
																									self.__reassign_nodes(snake_case   ,     node.left )
																		else:
																									snake_case_           =					self.get_max(
																									    node.left )  # Gets the max value of the left branch
																									self.remove(tmp_node.value )  # type: ignore
																									snake_case_           =					(
																									    tmp_node.value  # type: ignore
																									)  # Assigns the value to the node to delete and keep tree structure




				def 					a							(      self   ,     snake_case ):
											if node is not None:
																		yield node  # Preorder Traversal
																		yield from self.preorder_traverse(node.left )
																		yield from self.preorder_traverse(node.right )




				def 					a							(      self   ,     snake_case=None ):
											if traversal_function is None:
																		return self.preorder_traverse(self.root )
											else:
																		return traversal_function(self.root )




				def 					a							(      self   ,     snake_case   ,     snake_case ):
											if node:
																		self.inorder(snake_case   ,     node.left )
																		arr.append(node.value )
																		self.inorder(snake_case   ,     node.right )




				def 					a							(      self   ,     snake_case   ,     snake_case ):
											snake_case_           =					[]
											self.inorder(snake_case   ,     snake_case )  # append all values to list using inorder traversal
											return arr[k - 1]





def       __lowerCamelCase			(				UpperCamelCase__   ):







							'''simple docstring'''






							snake_case_           =					[]
							if curr_node is not None:
														snake_case_           =					postorder(curr_node.left   ) + postorder(curr_node.right   ) + [curr_node]
							return node_list





def       __lowerCamelCase			(				):







							'''simple docstring'''






							snake_case_           =					(8, 3, 6, 1, 10, 14, 13, 4, 7)
							snake_case_           =					BinarySearchTree()
							for i in testlist:
														t.insert(UpperCamelCase__   )

							# Prints all the elements of the list in order traversal
							print(UpperCamelCase__   )

							if t.search(6   ) is not None:
														print('The value 6 exists'   )
							else:
														print('The value 6 doesn\'t exist'   )

							if t.search(-1   ) is not None:
														print('The value -1 exists'   )
							else:
														print('The value -1 doesn\'t exist'   )

							if not t.empty():
														print('Max Value: '     ,							t.get_max().value   )  # type: ignore
														print('Min Value: '     ,							t.get_min().value   )  # type: ignore

							for i in testlist:
														t.remove(UpperCamelCase__   )
														print(UpperCamelCase__   )


if __name__ == "__main__":
					import doctest

					doctest.testmod(verbose=True)







_UpperCAmelCase	:     str		       = [0, 2, 4, 6, 8]
_UpperCAmelCase	:     Any		       = [1, 3, 5, 7, 9]





def       __lowerCamelCase			(				UpperCamelCase__     ,							UpperCamelCase__     ,							UpperCamelCase__     ,							UpperCamelCase__   ):







							'''simple docstring'''






							if remaining_length == 0:
														if digits[0] == 0 or digits[-1] == 0:
																					return 0

														for i in range(length // 2 - 1     ,							-1     ,							-1   ):
																					remainder += digits[i] + digits[length - i - 1]

																					if remainder % 2 == 0:
																												return 0

																					remainder //= 10

														return 1

							if remaining_length == 1:
														if remainder % 2 == 0:
																					return 0

														snake_case_           =					0
														for digit in range(10   ):
																					snake_case_           =					digit
																					result += reversible_numbers(
																					    0     ,							(remainder + 2 * digit) // 10     ,							UpperCamelCase__     ,							UpperCamelCase__   )
														return result

							snake_case_           =					0
							for digita in range(10   ):
														snake_case_           =					digita

														if (remainder + digita) % 2 == 0:
																					snake_case_           =					ODD_DIGITS
														else:
																					snake_case_           =					EVEN_DIGITS

														for digita in other_parity_digits:
																					snake_case_           =					digita
																					result += reversible_numbers(
																					    remaining_length - 2     ,							(remainder + digita + digita) // 10     ,							UpperCamelCase__     ,							UpperCamelCase__     ,							)
							return result





def       __lowerCamelCase			(				UpperCamelCase__ = 9   ):







							'''simple docstring'''






							snake_case_           =					0
							for length in range(1     ,							max_power + 1   ):
														result += reversible_numbers(UpperCamelCase__     ,							0     ,							[0] * length     ,							UpperCamelCase__   )
							return result


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




