

from __future__ import annotations

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






class 							A_			(		snake_case__ ):


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


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


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







_a			=       TypeVar('''T''', bound=Comparable)






class 							A_			(		Generic[T] ):


     def __init__(							self      :		Optional[int] )							->     None:
      __lowerCAmelCase:       list[T]            =				[]
      __lowerCAmelCase:       int            =				0


     def __repr__(							self      :		int )							->     str:
      return str(self.h )


     def   UpperCAmelCase  (							self      :		Tuple      ,  UpperCAmelCase      :		int )							->     int | None:
      if child_idx > 0:
       return (child_idx - 1) // 2
      return None


     def   UpperCAmelCase  (							self      :		List[Any]      ,  UpperCAmelCase      :		int )							->     int | None:
      __lowerCAmelCase:       List[Any]            =				2 * parent_idx + 1
      if left_child_index < self.heap_size:
       return left_child_index
      return None


     def   UpperCAmelCase  (							self      :		int      ,  UpperCAmelCase      :		int )							->     int | None:
      __lowerCAmelCase:       List[str]            =				2 * parent_idx + 2
      if right_child_index < self.heap_size:
       return right_child_index
      return None


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


     def   UpperCAmelCase  (							self      :		List[str]      ,  UpperCAmelCase      :		Iterable[T] )							->     None:
      __lowerCAmelCase:       Any            =				list(UpperCAmelCase )
      __lowerCAmelCase:       Optional[Any]            =				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(UpperCAmelCase )


     def   UpperCAmelCase  (							self      :		str )							->     T:
      if self.heap_size >= 2:
       __lowerCAmelCase:       Dict            =				self.h[0]
       __lowerCAmelCase:       Tuple            =				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   UpperCAmelCase  (							self      :		Any      ,  UpperCAmelCase      :		T )							->     None:
      self.h.append(UpperCAmelCase )
      __lowerCAmelCase:       Tuple            =				(self.heap_size - 1) // 2
      self.heap_size += 1
      while idx >= 0:
       self.max_heapify(UpperCAmelCase )
       __lowerCAmelCase:       str            =				(idx - 1) // 2


     def   UpperCAmelCase  (							self      :		str )							->     None:
      __lowerCAmelCase:       Any            =				self.heap_size
      for j in range(size - 1      ,  0      ,  -1 ):
       __lowerCAmelCase     ,							__lowerCAmelCase:       str            =				self.h[j], self.h[0]
       self.heap_size -= 1
       self.max_heapify(0 )
      __lowerCAmelCase:       Optional[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, 1_0, 8],
      [1_0_3, 9, 1, 7, 1_1, 1_5, 2_5, 2_0_1, 2_0_9, 1_0_7, 5],
      [-4_5, -2, -5],
  ]:
    print(f"unsorted array: {unsorted}")

    _a			=       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(1_0_0)
    print(f"after new value 100 inserted: {heap}")

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








from __future__ import annotations







def _a			(	SCREAMING_SNAKE_CASE		:      list[int]		)   ->   list[int]:

 """simple docstring"""






 if not list_of_ints:
  return []

 if min(SCREAMING_SNAKE_CASE		) < 0:
  raise ValueError('All numbers must be positive'		)

 __lowerCAmelCase:       Tuple            =				max(len(bin(SCREAMING_SNAKE_CASE		)[2:]		) for x in list_of_ints		)
 return _msd_radix_sort(SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE		)







def _a			(	SCREAMING_SNAKE_CASE		:      list[int]   , SCREAMING_SNAKE_CASE		:      int		)   ->   list[int]:

 """simple docstring"""






 if bit_position == 0 or len(SCREAMING_SNAKE_CASE		) in [0, 1]:
  return list_of_ints

 __lowerCAmelCase:       List[str]            =				[]
 __lowerCAmelCase:       Any            =				[]
 # Split numbers based on bit at bit_position from the right
 for number in list_of_ints:
  if (number >> (bit_position - 1)) & 1:
   # number has a one at bit bit_position
   ones.append(SCREAMING_SNAKE_CASE		)
  else:
   # number has a zero at bit bit_position
   zeros.append(SCREAMING_SNAKE_CASE		)

    # recursively split both lists further
 __lowerCAmelCase:       Dict            =				_msd_radix_sort(SCREAMING_SNAKE_CASE   , bit_position - 1		)
 __lowerCAmelCase:       Union[str, Any]            =				_msd_radix_sort(SCREAMING_SNAKE_CASE   , bit_position - 1		)

 # recombine lists
 __lowerCAmelCase:       List[str]            =				zeros
 res.extend(SCREAMING_SNAKE_CASE		)

 return res







def _a			(	SCREAMING_SNAKE_CASE		:      list[int]		)   ->   List[str]:

 """simple docstring"""






 __lowerCAmelCase:       Optional[int]            =				len(SCREAMING_SNAKE_CASE		)
 if not list_of_ints or length == 1:
  return

 if min(SCREAMING_SNAKE_CASE		) < 0:
  raise ValueError('All numbers must be positive'		)

 __lowerCAmelCase:       Optional[int]            =				max(len(bin(SCREAMING_SNAKE_CASE		)[2:]		) for x in list_of_ints		)
 _msd_radix_sort_inplace(SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE   , 0   , SCREAMING_SNAKE_CASE		)







def _a			(	SCREAMING_SNAKE_CASE		:      list[int]   , SCREAMING_SNAKE_CASE		:      int   , SCREAMING_SNAKE_CASE		:      int   , SCREAMING_SNAKE_CASE		:      int		)   ->   str:

 """simple docstring"""






 if bit_position == 0 or end_index - begin_index <= 1:
  return

 bit_position -= 1

 __lowerCAmelCase:       Optional[int]            =				begin_index
 __lowerCAmelCase:       Optional[Any]            =				end_index - 1
 while i <= j:
  __lowerCAmelCase:       Any            =				False
  if not (list_of_ints[i] >> bit_position) & 1:
   # found zero at the beginning
   i += 1
   __lowerCAmelCase:       Optional[Any]            =				True
  if (list_of_ints[j] >> bit_position) & 1:
   # found one at the end
   j -= 1
   __lowerCAmelCase:       List[str]            =				True

  if changed:
   continue

  __lowerCAmelCase     ,							__lowerCAmelCase:       Union[str, Any]            =				list_of_ints[j], list_of_ints[i]
  j -= 1
  if j != i:
   i += 1

 _msd_radix_sort_inplace(SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE		)
 _msd_radix_sort_inplace(SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE   , SCREAMING_SNAKE_CASE		)


if __name__ == "__main__":
  import doctest

  doctest.testmod()





