





"""simple docstring"""




from __future__ import annotations

from abc import abstractmethod
from collections.abc import Iterable
from typing import Generic, Protocol, TypeVar




class 				_a		(   _lowerCAmelCase       ):






				@abstractmethod
				def __lt__(				self	:					T,				lowerCAmelCase__	:					T							)			->   bool:




										'''simple docstring'''



										pass






				@abstractmethod
				def __gt__(				self	:					T,				lowerCAmelCase__	:					T							)			->   bool:




										'''simple docstring'''



										pass






				@abstractmethod
				def __eq__(				self	:					T,				lowerCAmelCase__	:					object							)			->   bool:




										'''simple docstring'''



										pass

UpperCamelCase_     =TypeVar("""T""", bound=Comparable)




class 				_a		(   Generic[T]       ):






				def __init__(				self	:					str							)			->   None:




										'''simple docstring'''



										_UpperCamelCase    :      list[T]						     =					[]
										_UpperCamelCase    :      int						     =					0






				def __repr__(				self	:					List[Any]							)			->   str:




										'''simple docstring'''



										return str(self.h							)






				def        snake_case			(				self	:					Optional[int],				lowerCAmelCase__	:					int							)			->   int | None:




										'''simple docstring'''



										if child_idx > 0:
																return (child_idx - 1) // 2
										return None






				def        snake_case			(				self	:					Union[str, Any],				lowerCAmelCase__	:					int							)			->   int | None:




										'''simple docstring'''



										_UpperCamelCase    :      int						     =					2 * parent_idx + 1
										if left_child_index < self.heap_size:
																return left_child_index
										return None






				def        snake_case			(				self	:					int,				lowerCAmelCase__	:					int							)			->   int | None:




										'''simple docstring'''



										_UpperCamelCase    :      Optional[Any]						     =					2 * parent_idx + 2
										if right_child_index < self.heap_size:
																return right_child_index
										return None






				def        snake_case			(				self	:					Tuple,				lowerCAmelCase__	:					int							)			->   None:




										'''simple docstring'''



										if index < self.heap_size:
																_UpperCamelCase    :      int						     =					index
																_UpperCamelCase    :      Optional[Any]						     =					self.left_child_idx(lowerCAmelCase__							)
																_UpperCamelCase    :      Tuple						     =					self.right_child_idx(lowerCAmelCase__							)
																# check which child is larger than its parent
																if left_child is not None and self.h[left_child] > self.h[violation]:
																						_UpperCamelCase    :      List[Any]						     =					left_child
																if right_child is not None and self.h[right_child] > self.h[violation]:
																						_UpperCamelCase    :      List[Any]						     =					right_child
																# if violation indeed exists
																if violation != index:
																						# swap to fix the violation
																						_UpperCamelCase     ,							_UpperCamelCase    :      Any						     =					self.h[index], self.h[violation]
																						# fix the subsequent violation recursively if any
																						self.max_heapify(lowerCAmelCase__							)






				def        snake_case			(				self	:					int,				lowerCAmelCase__	:					Iterable[T]							)			->   None:




										'''simple docstring'''



										_UpperCamelCase    :      str						     =					list(lowerCAmelCase__							)
										_UpperCamelCase    :      str						     =					len(self.h							)
										if self.heap_size > 1:
																# max_heapify from right to left but exclude leaves (last level)
																for i in range(self.heap_size // 2 - 1,				-1,				-1							):
																						self.max_heapify(lowerCAmelCase__							)






				def        snake_case			(				self	:					Any							)			->   T:




										'''simple docstring'''



										if self.heap_size >= 2:
																_UpperCamelCase    :      Optional[int]						     =					self.h[0]
																_UpperCamelCase    :      Optional[int]						     =					self.h.pop(-1							)
																self.heap_size -= 1
																self.max_heapify(0							)
																return me
										elif self.heap_size == 1:
																self.heap_size -= 1
																return self.h.pop(-1							)
										else:
																raise Exception('''Empty heap'''							)






				def        snake_case			(				self	:					List[Any],				lowerCAmelCase__	:					T							)			->   None:




										'''simple docstring'''



										self.h.append(lowerCAmelCase__							)
										_UpperCamelCase    :      Dict						     =					(self.heap_size - 1) // 2
										self.heap_size += 1
										while idx >= 0:
																self.max_heapify(lowerCAmelCase__							)
																_UpperCamelCase    :      Dict						     =					(idx - 1) // 2






				def        snake_case			(				self	:					Any							)			->   None:




										'''simple docstring'''



										_UpperCamelCase    :      Tuple						     =					self.heap_size
										for j in range(size - 1,				0,				-1							):
																_UpperCamelCase     ,							_UpperCamelCase    :      Tuple						     =					self.h[j], self.h[0]
																self.heap_size -= 1
																self.max_heapify(0							)
										_UpperCamelCase    :      int						     =					size


if __name__ == "__main__":
						import doctest

						# run doc test
						doctest.testmod()

						# demo
						for unsorted in [
						    [0],
						    [2],
						    [3, 5],
						    [5, 3],
						    [5, 5],
						    [0, 0, 0, 0],
						    [1, 1, 1, 1],
						    [2, 2, 3, 5],
						    [0, 2, 2, 3, 5],
						    [2, 5, 3, 0, 2, 3, 0, 3],
						    [6, 1, 2, 7, 9, 3, 4, 5, 10, 8],
						    [103, 9, 1, 7, 11, 15, 25, 201, 209, 107, 5],
						    [-45, -2, -5],
						]:
												print(F"unsorted array: {unsorted}")

												UpperCamelCase_     =Heap()
												heap.build_max_heap(unsorted)
												print(F"after build heap: {heap}")

												print(F"max value: {heap.extract_max()}")
												print(F"after max value removed: {heap}")

												heap.insert(100)
												print(F"after new value 100 inserted: {heap}")

												heap.heap_sort()
												print(F"heap-sorted array: {heap}\n")










"""simple docstring"""




UpperCamelCase_     =1_000





def  a_       (							_lowercase     ):
						return x * x





def  a_       (							_lowercase ,		_lowercase ,		_lowercase ,		_lowercase = 4     ):
						assert callable(
						    _lowercase     ), F"""the function(object) passed should be callable your input : {function}"""
						assert isinstance(_lowercase ,		(float, int)     ), F"""a should be float or integer your input : {a}"""
						assert isinstance(function(_lowercase     ) ,		(float, int)     ), (
						    "the function should return integer or float return type of your function, "
						    F"""{type(_lowercase     )}"""
						)
						assert isinstance(_lowercase ,		(float, int)     ), F"""b should be float or integer your input : {b}"""
						assert (
						    isinstance(_lowercase ,		_lowercase     ) and precision > 0
						), F"""precision should be positive integer your input : {precision}"""

						# just applying the formula of simpson for approximate integration written in
						# mentioned article in first comment of this file and above this function

						_UpperCamelCase    :      str						     =					(b - a) / N_STEPS
						_UpperCamelCase    :      Dict						     =					function(_lowercase     ) + function(_lowercase     )

						for i in range(1 ,		_lowercase     ):
												_UpperCamelCase    :      List[Any]						     =					a + h * i
												result += function(_lowercase     ) * (4 if i % 2 else 2)

						result *= h / 3
						return round(_lowercase ,		_lowercase     )


if __name__ == "__main__":
						import doctest

						doctest.testmod()



