code: 
  
  from __future__ import annotations
  
  import unittest
  from collections.abc import Iterator
  
  
  
  
  
  
  class     lowerCamelCase_			:
  
  
  
  
  	def __init__(    self	:    str				,			__A	:    int				,			__A	:    Node | None       ):
  		__A   : Optional[int]								= label
  		__A   : Optional[int]								= parent
  		__A   : Node | None								= None
  		__A   : Node | None								= None
  
  
  
  
  
  
  class     lowerCamelCase_			:
  
  
  
  
  	def __init__(    self	:    str       ):
  		__A   : Node | None								= None
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Dict       ):
  		__A   : str								= None
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    List[str]       ):
  		return self.root is None
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Any				,			__A	:    int       ):
  		__A   : int								= self._put(self.root				,			__A       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Optional[Any]				,			__A	:    Node | None				,			__A	:    int				,			__A	:    Node | None = None       ):
  		if node is None:
  			__A   : Union[str, Any]								= Node(__A				,			__A       )
  		else:
  			if label < node.label:
  				__A   : Tuple								= self._put(node.left				,			__A				,			__A       )
  			elif label > node.label:
  				__A   : str								= self._put(node.right				,			__A				,			__A       )
  			else:
  				__A   : List[Any]								= F"""Node with label {label} already exists"""
  				raise Exception(__A       )
  
  		return node
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    List[str]				,			__A	:    int       ):
  		return self._search(self.root				,			__A       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Union[str, Any]				,			__A	:    Node | None				,			__A	:    int       ):
  		if node is None:
  			__A   : Dict								= F"""Node with label {label} does not exist"""
  			raise Exception(__A       )
  		else:
  			if label < node.label:
  				__A   : List[str]								= self._search(node.left				,			__A       )
  			elif label > node.label:
  				__A   : Optional[Any]								= self._search(node.right				,			__A       )
  
  		return node
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Tuple				,			__A	:    int       ):
  		__A   : int								= self.search(__A       )
  		if node.right and node.left:
  			__A   : int								= self._get_lowest_node(node.right       )
  			__A   : Dict								= node.left
  			__A   : List[str]								= node.right
  			__A   : Optional[Any]								= lowest_node
  			if node.right:
  				__A   : List[str]								= lowest_node
  			self._reassign_nodes(__A				,			__A       )
  		elif not node.right and node.left:
  			self._reassign_nodes(__A				,			node.left       )
  		elif node.right and not node.left:
  			self._reassign_nodes(__A				,			node.right       )
  		else:
  			self._reassign_nodes(__A				,			__A       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    List[Any]				,			__A	:    Node				,			__A	:    Node | None       ):
  		if new_children:
  			__A   : Optional[Any]								= node.parent
  
  		if node.parent:
  			if node.parent.right == node:
  				__A   : Dict								= new_children
  			else:
  				__A   : str								= new_children
  		else:
  			__A   : Optional[Any]								= new_children
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Optional[Any]				,			__A	:    Node       ):
  		if node.left:
  			__A   : Union[str, Any]								= self._get_lowest_node(node.left       )
  		else:
  			__A   : Any								= node
  			self._reassign_nodes(__A				,			node.right       )
  
  		return lowest_node
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    str				,			__A	:    int       ):
  		try:
  			self.search(__A       )
  			return True
  		except Exception:
  			return False
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Union[str, Any]       ):
  		if self.root is None:
  			raise Exception("""Binary search tree is empty"""       )
  
  		__A   : Dict								= self.root
  		while node.right is not None:
  			__A   : Dict								= node.right
  
  		return node.label
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    str       ):
  		if self.root is None:
  			raise Exception("""Binary search tree is empty"""       )
  
  		__A   : Optional[Any]								= self.root
  		while node.left is not None:
  			__A   : int								= node.left
  
  		return node.label
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Union[str, Any]       ):
  		return self._inorder_traversal(self.root       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    int				,			__A	:    Node | None       ):
  		if node is not None:
  			yield from self._inorder_traversal(node.left       )
  			yield node
  			yield from self._inorder_traversal(node.right       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Any       ):
  		return self._preorder_traversal(self.root       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Optional[Any]				,			__A	:    Node | None       ):
  		if node is not None:
  			yield node
  			yield from self._preorder_traversal(node.left       )
  			yield from self._preorder_traversal(node.right       )
  
  
  
  
  
  
  class     lowerCamelCase_			(  unittest.TestCase  ):
  
  
  
  
  	@staticmethod
  	def 					lowerCAmelCase_					(    ):
  		__A   : Union[str, Any]								= BinarySearchTree()
  		t.put(8       )
  		t.put(3       )
  		t.put(6       )
  		t.put(1       )
  		t.put(10       )
  		t.put(14       )
  		t.put(13       )
  		t.put(4       )
  		t.put(7       )
  		t.put(5       )
  
  		return t
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    List[str]       ):
  		__A   : Optional[int]								= BinarySearchTree()
  		assert t.is_empty()
  
  		t.put(8       )
  		assert t.root is not None
  		assert t.root.parent is None
  		assert t.root.label == 8
  
  		t.put(10       )
  		assert t.root.right is not None
  		assert t.root.right.parent == t.root
  		assert t.root.right.label == 10
  
  		t.put(3       )
  		assert t.root.left is not None
  		assert t.root.left.parent == t.root
  		assert t.root.left.label == 3
  
  		t.put(6       )
  		assert t.root.left.right is not None
  		assert t.root.left.right.parent == t.root.left
  		assert t.root.left.right.label == 6
  
  		t.put(1       )
  		assert t.root.left.left is not None
  		assert t.root.left.left.parent == t.root.left
  		assert t.root.left.left.label == 1
  
  		with self.assertRaises(__A       ):  # noqa: B017
  			t.put(1       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Tuple       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  
  		__A   : str								= t.search(6       )
  		assert node.label == 6
  
  		__A   : List[str]								= t.search(13       )
  		assert node.label == 13
  
  		with self.assertRaises(__A       ):  # noqa: B017
  			t.search(2       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Dict       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  
  		t.remove(13       )
  		assert t.root is not None
  		assert t.root.right is not None
  		assert t.root.right.right is not None
  		assert t.root.right.right.right is None
  		assert t.root.right.right.left is None
  
  		t.remove(7       )
  		assert t.root.left is not None
  		assert t.root.left.right is not None
  		assert t.root.left.right.left is not None
  		assert t.root.left.right.right is None
  		assert t.root.left.right.left.label == 4
  
  		t.remove(6       )
  		assert t.root.left.left is not None
  		assert t.root.left.right.right is not None
  		assert t.root.left.left.label == 1
  		assert t.root.left.right.label == 4
  		assert t.root.left.right.right.label == 5
  		assert t.root.left.right.left is None
  		assert t.root.left.left.parent == t.root.left
  		assert t.root.left.right.parent == t.root.left
  
  		t.remove(3       )
  		assert t.root is not None
  		assert t.root.left.label == 4
  		assert t.root.left.right.label == 5
  		assert t.root.left.left.label == 1
  		assert t.root.left.parent == t.root
  		assert t.root.left.left.parent == t.root.left
  		assert t.root.left.right.parent == t.root.left
  
  		t.remove(4       )
  		assert t.root.left is not None
  		assert t.root.left.left is not None
  		assert t.root.left.label == 5
  		assert t.root.left.right is None
  		assert t.root.left.left.label == 1
  		assert t.root.left.parent == t.root
  		assert t.root.left.left.parent == t.root.left
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    str       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  
  		t.remove(3       )
  		assert t.root is not None
  		assert t.root.left is not None
  		assert t.root.left.left is not None
  		assert t.root.left.right is not None
  		assert t.root.left.right.left is not None
  		assert t.root.left.right.right is not None
  		assert t.root.left.label == 4
  		assert t.root.left.right.label == 6
  		assert t.root.left.left.label == 1
  		assert t.root.left.right.right.label == 7
  		assert t.root.left.right.left.label == 5
  		assert t.root.left.parent == t.root
  		assert t.root.left.right.parent == t.root.left
  		assert t.root.left.left.parent == t.root.left
  		assert t.root.left.right.left.parent == t.root.left.right
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    str       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  		t.empty()
  		assert t.root is None
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Union[str, Any]       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  		assert not t.is_empty()
  
  		t.empty()
  		assert t.is_empty()
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Tuple       ):
  		__A   : Any								= self._get_binary_search_tree()
  
  		assert t.exists(6       )
  		assert not t.exists(-1       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    int       ):
  		__A   : Union[str, Any]								= self._get_binary_search_tree()
  
  		assert t.get_max_label() == 14
  
  		t.empty()
  		with self.assertRaises(__A       ):  # noqa: B017
  			t.get_max_label()
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Tuple       ):
  		__A   : List[Any]								= self._get_binary_search_tree()
  
  		assert t.get_min_label() == 1
  
  		t.empty()
  		with self.assertRaises(__A       ):  # noqa: B017
  			t.get_min_label()
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    List[Any]       ):
  		__A   : Optional[int]								= self._get_binary_search_tree()
  
  		__A   : List[Any]								= [i.label for i in t.inorder_traversal()]
  		assert inorder_traversal_nodes == [1, 3, 4, 5, 6, 7, 8, 10, 13, 14]
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Any       ):
  		__A   : Optional[Any]								= self._get_binary_search_tree()
  
  		__A   : List[Any]								= [i.label for i in t.preorder_traversal()]
  		assert preorder_traversal_nodes == [8, 3, 1, 6, 4, 5, 7, 10, 14, 13]
  
  
  
  
  
  
  def        __SCREAMING_SNAKE_CASE    (      )				->							None:
  	__A   : Optional[int]								= BinarySearchTree()
  	t.put(8					)
  	t.put(3					)
  	t.put(6					)
  	t.put(1					)
  	t.put(10					)
  	t.put(14					)
  	t.put(13					)
  	t.put(4					)
  	t.put(7					)
  	t.put(5					)
  
  	print(
  	    """
              8
             / \\
            3   10
           / \\    \\
          1   6    14
             / \\   /
            4   7 13
             \\
              5
          """					)
  
  	print("""Label 6 exists:""" ,t.exists(6					)					)
  	print("""Label 13 exists:""" ,t.exists(13					)					)
  	print("""Label -1 exists:""" ,t.exists(-1					)					)
  	print("""Label 12 exists:""" ,t.exists(12					)					)
  
  	# Prints all the elements of the list in inorder traversal
  	__A   : int								= [i.label for i in t.inorder_traversal()]
  	print("""Inorder traversal:""" ,a__					)
  
  	# Prints all the elements of the list in preorder traversal
  	__A   : Any								= [i.label for i in t.preorder_traversal()]
  	print("""Preorder traversal:""" ,a__					)
  
  	print("""Max. label:""" ,t.get_max_label()					)
  	print("""Min. label:""" ,t.get_min_label()					)
  
  	# Delete elements
  	print("""\nDeleting elements 13, 10, 8, 3, 6, 14"""					)
  	print(
  	    """
            4
           / \\
          1   7
               \\
                5
          """					)
  	t.remove(13					)
  	t.remove(10					)
  	t.remove(8					)
  	t.remove(3					)
  	t.remove(6					)
  	t.remove(14					)
  
  	# Prints all the elements of the list in inorder traversal after delete
  	__A   : Dict								= [i.label for i in t.inorder_traversal()]
  	print("""Inorder traversal after delete:""" ,a__					)
  
  	# Prints all the elements of the list in preorder traversal after delete
  	__A   : List[Any]								= [i.label for i in t.preorder_traversal()]
  	print("""Preorder traversal after delete:""" ,a__					)
  
  	print("""Max. label:""" ,t.get_max_label()					)
  	print("""Min. label:""" ,t.get_min_label()					)
  
  
  if __name__ == "__main__":
  			binary_search_tree_example()
  
  
  
  
  
  
style_context: 
  
  import math
  
  
  
  
  
  
  class     lowerCamelCase_			:
  
  
  
  
  	def __init__(    self	:    Dict				,			__A	:    int				,			__A	:    int				,			__A	:    int				,			__A	:    Any       ):
  		__A   : Union[str, Any]								= x
  		__A   : Union[str, Any]								= y
  		__A   : Optional[int]								= step_size
  		__A   : Dict								= function_to_optimize
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    Optional[int]       ):
  		return self.function(self.x				,			self.y       )
  
  
  
  
  	def 					lowerCAmelCase_					(    self	:    int       ):
  		__A   : Dict								= self.step_size
  		return [
  		    SearchProblem(__A				,			__A				,			__A				,			self.function       )
  		    for x, y in (
  		        (self.x - step_size, self.y - step_size),
  		        (self.x - step_size, self.y),
  		        (self.x - step_size, self.y + step_size),
  		        (self.x, self.y - step_size),
  		        (self.x, self.y + step_size),
  		        (self.x + step_size, self.y - step_size),
  		        (self.x + step_size, self.y),
  		        (self.x + step_size, self.y + step_size),
  		    )
  		]
  
  
  
  
  	def __hash__(    self	:    str       ):
  		return hash(str(self       )       )
  
  
  
  
  	def __eq__(    self	:    Union[str, Any]				,			__A	:    Optional[int]       ):
  		if isinstance(__A				,			__A       ):
  			return hash(str(self       )       ) == hash(str(__A       )       )
  		return False
  
  
  
  
  	def __str__(    self	:    List[Any]       ):
  		return F"""x: {self.x} y: {self.y}"""
  
  
  
  
  
  
  def        __SCREAMING_SNAKE_CASE    (      a__						:      Optional[Any] ,a__						:      bool = True ,a__						:      float = math.inf ,a__						:      float = -math.inf ,a__						:      float = math.inf ,a__						:      float = -math.inf ,a__						:      bool = False ,a__						:      int = 10000 ,)				->							SearchProblem:
  	__A   : int								= search_prob
  	__A   : List[str]								= []  # list to store the current score at each iteration
  	__A   : Optional[Any]								= 0
  	__A   : Any								= False
  	__A   : Dict								= set()
  	while not solution_found and iterations < max_iter:
  		visited.add(a__					)
  		iterations += 1
  		__A   : Union[str, Any]								= current_state.score()
  		scores.append(a__					)
  		__A   : List[Any]								= current_state.get_neighbors()
  		__A   : Tuple								= -math.inf
  		__A   : str								= math.inf
  		__A   : Optional[int]								= None  # to hold the next best neighbor
  		for neighbor in neighbors:
  			if neighbor in visited:
  				continue  # do not want to visit the same state again
  			if (
  			    neighbor.x > max_x
  			    or neighbor.x < min_x
  			    or neighbor.y > max_y
  			    or neighbor.y < min_y
  			):
  				continue  # neighbor outside our bounds
  			__A   : int								= neighbor.score() - current_score
  			if find_max:  # finding max
  				# going to direction with greatest ascent
  				if change > max_change and change > 0:
  					__A   : str								= change
  					__A   : Optional[int]								= neighbor
  			else:  # finding min
  				# to direction with greatest descent
  				if change < min_change and change < 0:
  					__A   : List[Any]								= change
  					__A   : List[str]								= neighbor
  		if next_state is not None:
  			# we found at least one neighbor which improved the current state
  			__A   : Tuple								= next_state
  		else:
  			# since we have no neighbor that improves the solution we stop the search
  			__A   : str								= True
  
  	if visualization:
  		from matplotlib import pyplot as plt
  
  		plt.plot(range(a__					) ,a__					)
  		plt.xlabel("""Iterations"""					)
  		plt.ylabel("""Function values"""					)
  		plt.show()
  
  	return current_state
  
  
  if __name__ == "__main__":
  			import doctest
  
  			doctest.testmod()
  			def        __SCREAMING_SNAKE_CASE    (      a__						:      str ,a__						:      Any					)				->							Dict:
  				return (x**2) + (y**2)
  
  			# starting the problem with initial coordinates (3, 4)
  			UpperCAmelCase_       :				Tuple		   =      SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
  			UpperCAmelCase_       :				Any		   =      hill_climbing(prob, find_max=False)
  			print(
  			    '''The minimum score for f(x, y) = x^2 + y^2 found via hill climbing: '''
  			    f"""{local_min.score()}"""
  			)
  
  			# starting the problem with initial coordinates (12, 47)
  			UpperCAmelCase_       :				List[Any]		   =      SearchProblem(x=12, y=47, step_size=1, function_to_optimize=test_fa)
  			UpperCAmelCase_       :				Any		   =      hill_climbing(
  			    prob, find_max=False, max_x=100, min_x=5, max_y=50, min_y=-5, visualization=True
  			)
  			print(
  			    '''The minimum score for f(x, y) = x^2 + y^2 with the domain 100 > x > 5 '''
  			    f"""and 50 > y > - 5 found via hill climbing: {local_min.score()}"""
  			)
  			def        __SCREAMING_SNAKE_CASE    (      a__						:      int ,a__						:      List[str]					)				->							Any:
  				return (3 * x**2) - (6 * y)
  
  			UpperCAmelCase_       :				Tuple		   =      SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
  			UpperCAmelCase_       :				Dict		   =      hill_climbing(prob, find_max=True)
  
  
  
  
  
  
  
  			print(
  			    '''The maximum score for f(x, y) = x^2 + y^2 found via hill climbing: '''
  			    f"""{local_min.score()}"""
  			)
  
  
  
  
  
  