


"""simple docstring"""





class  lowercase_  :







      def __init__(      self :							List[str]		,  _lowercase :							Union[str, Any]    ):
        lowerCAmelCase__    :    Any								=					data
        lowerCAmelCase__    :    Optional[Any]								=					None
        lowerCAmelCase__    :    List[str]								=					None







      def __str__(      self :							str    ):
        return f"{self.data}"

class  lowercase_  :







      def __init__(      self :							List[Any]    ):
        lowerCAmelCase__    :    Dict								=					None
        lowerCAmelCase__    :    Optional[Any]								=					None







      def __iter__(      self :							Optional[int]    ):
        lowerCAmelCase__    :    List[str]								=					self.head
        while node:
          yield node.data
          lowerCAmelCase__    :    Dict								=					node.next







      def __str__(      self :							List[str]    ):
        return "->".join([str(_lowercase    ) for item in self]    )







      def __len__(      self :							List[Any]    ):
        return sum(1 for _ in self    )







      def 				_lowerCAmelCase       (      self :							List[str]		,  _lowercase :							int    ):
        self.insert_at_nth(0		,  _lowercase    )







      def 				_lowerCAmelCase       (      self :							Dict		,  _lowercase :							Optional[int]    ):
        self.insert_at_nth(len(self    )		,  _lowercase    )







      def 				_lowerCAmelCase       (      self :							Optional[Any]		,  _lowercase :							int		,  _lowercase :							Dict    ):
        lowerCAmelCase__    :    Tuple								=					len(self    )

        if not 0 <= index <= length:
          raise IndexError("list index out of range"    )
        lowerCAmelCase__    :    str								=					Node(_lowercase    )
        if self.head is None:
          lowerCAmelCase__    :    Optional[int]								=					new_node
        elif index == 0:
          lowerCAmelCase__    :    Optional[int]								=					new_node
          lowerCAmelCase__    :    Union[str, Any]								=					self.head
          lowerCAmelCase__    :    str								=					new_node
        elif index == length:
          lowerCAmelCase__    :    Any								=					new_node
          lowerCAmelCase__    :    List[Any]								=					self.tail
          lowerCAmelCase__    :    Optional[Any]								=					new_node
        else:
          lowerCAmelCase__    :    Any								=					self.head
          for _ in range(0		,  _lowercase    ):
            lowerCAmelCase__    :    List[Any]								=					temp.next
          lowerCAmelCase__    :    List[str]								=					new_node
          lowerCAmelCase__    :    Optional[Any]								=					temp.previous
          lowerCAmelCase__    :    str								=					temp
          lowerCAmelCase__    :    List[str]								=					new_node







      def 				_lowerCAmelCase       (      self :							int    ):
        return self.delete_at_nth(0    )







      def 				_lowerCAmelCase       (      self :							Union[str, Any]    ):
        return self.delete_at_nth(len(self    ) - 1    )







      def 				_lowerCAmelCase       (      self :							List[Any]		,  _lowercase :							int    ):
        lowerCAmelCase__    :    Optional[int]								=					len(self    )

        if not 0 <= index <= length - 1:
          raise IndexError("list index out of range"    )
        lowerCAmelCase__    :    Any								=					self.head  # default first node
        if length == 1:
          lowerCAmelCase__    :    Union[str, Any]								=					None
        elif index == 0:
          lowerCAmelCase__    :    Dict								=					self.head.next
          lowerCAmelCase__    :    List[str]								=					None
        elif index == length - 1:
          lowerCAmelCase__    :    List[str]								=					self.tail
          lowerCAmelCase__    :    str								=					self.tail.previous
          lowerCAmelCase__    :    List[Any]								=					None
        else:
          lowerCAmelCase__    :    Tuple								=					self.head
          for _ in range(0		,  _lowercase    ):
            lowerCAmelCase__    :    Any								=					temp.next
          lowerCAmelCase__    :    str								=					temp
          lowerCAmelCase__    :    Union[str, Any]								=					temp.previous
          lowerCAmelCase__    :    List[str]								=					temp.next
        return delete_node.data







      def 				_lowerCAmelCase       (      self :							int		,  _lowercase :							List[Any]    ):
        lowerCAmelCase__    :    str								=					self.head

        while current.data != data:  # Find the position to delete
          if current.next:
            lowerCAmelCase__    :    str								=					current.next
          else:  # We have reached the end an no value matches
            raise ValueError("No data matching given value"    )

        if current == self.head:
          self.delete_head()

        elif current == self.tail:
          self.delete_tail()

        else:  # Before: 1 <--> 2(current) <--> 3
          lowerCAmelCase__    :    str								=					current.next  # 1 --> 3
          lowerCAmelCase__    :    int								=					current.previous  # 1 <--> 3
        return data







      def 				_lowerCAmelCase       (      self :							List[Any]    ):
        return len(self    ) == 0





def     lowercase__	(  )					->     None:
  lowerCAmelCase__    :    Optional[Any]								=					DoublyLinkedList()
  assert linked_list.is_empty() is True
  assert str(lowerCamelCase				) == ""

  try:
    linked_list.delete_head()
    raise AssertionError  # This should not happen.
  except IndexError:
    assert True  # This should happen.

  try:
    linked_list.delete_tail()
    raise AssertionError  # This should not happen.
  except IndexError:
    assert True  # This should happen.

  for i in range(1_0				):
    assert len(lowerCamelCase				) == i
    linked_list.insert_at_nth(lowerCamelCase				,	i + 1				)
  assert str(lowerCamelCase				) == "->".join(str(lowerCamelCase				) for i in range(1				,	1_1				)				)

  linked_list.insert_at_head(0				)
  linked_list.insert_at_tail(1_1				)
  assert str(lowerCamelCase				) == "->".join(str(lowerCamelCase				) for i in range(0				,	1_2				)				)

  assert linked_list.delete_head() == 0
  assert linked_list.delete_at_nth(9				) == 1_0
  assert linked_list.delete_tail() == 1_1
  assert len(lowerCamelCase				) == 9
  assert str(lowerCamelCase				) == "->".join(str(lowerCamelCase				) for i in range(1				,	1_0				)				)


if __name__ == "__main__":
   from doctest import testmod

   testmod()




"""simple docstring"""





from __future__ import annotations





def     lowercase__	(  lowerCamelCase     :  list				,	lowerCamelCase     :  list				)					->     list:
  lowerCAmelCase__    :    Dict								=					[None] * (len(lowerCamelCase				) + len(lowerCamelCase				))

  lowerCAmelCase__    :    Optional[Any]								=					0  # pointer to current index for left Half
  lowerCAmelCase__    :    Any								=					0  # pointer to current index for the right Half
  lowerCAmelCase__    :    Dict								=					0  # pointer to current index for the sorted array Half

  while pointera < len(lowerCamelCase				) and pointera < len(lowerCamelCase				):
    if left_half[pointera] < right_half[pointera]:
      lowerCAmelCase__    :    Tuple								=					left_half[pointera]
      pointera += 1
      index += 1
    else:
      lowerCAmelCase__    :    int								=					right_half[pointera]
      pointera += 1
      index += 1
  while pointera < len(lowerCamelCase				):
    lowerCAmelCase__    :    Tuple								=					left_half[pointera]
    pointera += 1
    index += 1

  while pointera < len(lowerCamelCase				):
    lowerCAmelCase__    :    Optional[int]								=					right_half[pointera]
    pointera += 1
    index += 1

  return sorted_array





def     lowercase__	(  lowerCamelCase     :  list				)					->     list:
  if len(lowerCamelCase				) <= 1:
    return array
  # the actual formula to calculate the middle element = left + (right - left) // 2
  # this avoids integer overflow in case of large N
  lowerCAmelCase__    :    Optional[int]								=					0 + (len(lowerCamelCase				) - 0) // 2

  # Split the array into halves till the array length becomes equal to One
  # merge the arrays of single length returned by mergeSort function and
  # pass them into the merge arrays function which merges the array
  lowerCAmelCase__    :    Union[str, Any]								=					array[:middle]
  lowerCAmelCase__    :    List[str]								=					array[middle:]

  return merge(merge_sort(lowerCamelCase				)				,	merge_sort(lowerCamelCase				)				)


if __name__ == "__main__":
   import doctest

   doctest.testmod()
