

"""simple docstring"""





from __future__ import annotations

from collections import deque
from enum import Enum
from math import atana, degrees
from sys import maxsize

class     __a   (      snake_case__    ):

			"""simple docstring"""

			SCREAMING_SNAKE_CASE_						     =						1
			SCREAMING_SNAKE_CASE_						     =						2
			SCREAMING_SNAKE_CASE_						     =						3






			def __repr__(							self     :					Optional[Any]						):
								return f'''{self.__class__.__name__}.{self.name}'''



def        _lowerCAmelCase      (						UpperCAmelCase     :							tuple[int, int]      ,							UpperCAmelCase     :							int      ,							UpperCAmelCase     :							int				):


					'''simple docstring'''






					UpperCamelCase__		:    Union[str, Any]         =point
					return degrees(atana(y - miny      ,							x - minx				)				)



def        _lowerCAmelCase      (						UpperCAmelCase     :							tuple[int, int]      ,							UpperCAmelCase     :							tuple[int, int]      ,							UpperCAmelCase     :							tuple[int, int]				):


					'''simple docstring'''






					UpperCamelCase__		:    int         =starting
					UpperCamelCase__		:    Optional[Any]         =via
					UpperCamelCase__		:    List[Any]         =target
					UpperCamelCase__		:    Optional[int]         =degrees(atana(ya - ya      ,							xa - xa				)				)
					via_angle %= 360
					UpperCamelCase__		:    List[Any]         =degrees(atana(ya - ya      ,							xa - xa				)				)
					target_angle %= 360
					# t-
					#  \ \
					#   \ v
					#    \|
					#     s
					# via_angle is always lower than target_angle, if direction is left.
					# If they are same, it means they are on a same line of convex hull.
					if target_angle > via_angle:
										return Direction.left
					elif target_angle == via_angle:
										return Direction.straight
					else:
										return Direction.right







def        _lowerCAmelCase      (						UpperCAmelCase     :							list[tuple[int, int]]				):


					'''simple docstring'''






					if len(UpperCAmelCase				) <= 2:
										# There is no convex hull
										raise ValueError('''graham_scan: argument must contain more than 3 points.'''				)
					if len(UpperCAmelCase				) == 3:
										return points
					# find the lowest and the most left point
					UpperCamelCase__		:    Any         =0
					UpperCamelCase__		:    str         =maxsize, maxsize
					for i, point in enumerate(UpperCAmelCase				):
										UpperCamelCase__		:    List[str]         =point[0]
										UpperCamelCase__		:    Optional[int]         =point[1]
										if y < miny:
															UpperCamelCase__		:    List[Any]         =y
															UpperCamelCase__		:    str         =x
															UpperCamelCase__		:    int         =i
										if y == miny and x < minx:
															UpperCamelCase__		:    Union[str, Any]         =x
															UpperCamelCase__		:    Dict         =i

    # remove the lowest and the most left point from points for preparing for sort
					points.pop(UpperCAmelCase				)

					UpperCamelCase__		:    Optional[int]         =sorted(UpperCAmelCase      ,							key=lambda UpperCAmelCase				: angle_comparer(UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase				)				)
					# This insert actually costs complexity,
					# and you should instead add (minx, miny) into stack later.
					# I'm using insert just for easy understanding.
					sorted_points.insert(0      ,							(minx, miny)				)

					UpperCamelCase__		:    deque[tuple[int, int]]         =deque()
					stack.append(sorted_points[0]				)
					stack.append(sorted_points[1]				)
					stack.append(sorted_points[2]				)
					# In any ways, the first 3 points line are towards left.
					# Because we sort them the angle from minx, miny.
					UpperCamelCase__		:    Optional[Any]         =Direction.left

					for i in range(3      ,							len(UpperCAmelCase				)				):
										while True:
															UpperCamelCase__		:    Union[str, Any]         =stack[-2]
															UpperCamelCase__		:    List[Any]         =stack[-1]
															UpperCamelCase__		:    int         =sorted_points[i]
															UpperCamelCase__		:    str         =check_direction(UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase				)

															if next_direction == Direction.left:
																				UpperCamelCase__		:    Union[str, Any]         =Direction.left
																				break
															if next_direction == Direction.straight:
																				if current_direction == Direction.left:
																									# We keep current_direction as left.
																									# Because if the straight line keeps as straight,
																									# we want to know if this straight line is towards left.
																									break
																				elif current_direction == Direction.right:
																									# If the straight line is towards right,
																									# every previous points on those straigh line is not convex hull.
																									stack.pop()
															if next_direction == Direction.right:
																				stack.pop()
										stack.append(sorted_points[i]				)
					return list(UpperCAmelCase				)





"""simple docstring"""





from __future__ import annotations

from collections.abc import Iterable
from dataclasses import dataclass
from typing import Any

class     __a   :

			"""simple docstring"""

			SCREAMING_SNAKE_CASE_						     =						('_front', '_back', '_len')

			@dataclass
			class     __a   :

						"""simple docstring"""

						SCREAMING_SNAKE_CASE_						     =						None
						SCREAMING_SNAKE_CASE_						     =						None
						SCREAMING_SNAKE_CASE_						     =						None



			class     __a   :

						"""simple docstring"""

						SCREAMING_SNAKE_CASE_						     =						('_cur',)






						def __init__(							self     :					Optional[int]						,  lowercase_     :					Deque._Node | None						):
											UpperCamelCase__		:    List[str]         =cur






						def __iter__(							self     :					List[str]						):
											return self






						def    _lowerCAmelCase			(							self     :					List[Any]						):
											if self._cur is None:
																# finished iterating
																raise StopIteration
											UpperCamelCase__		:    str         =self._cur.val
											UpperCamelCase__		:    Any         =self._cur.next_node

											return val






			def __init__(							self     :					str						,  lowercase_     :					Iterable[Any] | None = None						):
								UpperCamelCase__		:    Any         =None
								UpperCamelCase__		:    Any         =None
								UpperCamelCase__		:    int         =0

								if iterable is not None:
													# append every value to the deque
													for val in iterable:
																		self.append(lowercase_						)






			def    _lowerCAmelCase			(							self     :					str						,  lowercase_     :					Any						):
								UpperCamelCase__		:    Union[str, Any]         =self._Node(lowercase_						,  lowercase_						,  lowercase_						)
								if self.is_empty():
													# front = back
													UpperCamelCase__		:    Any         =node
													UpperCamelCase__		:    List[Any]         =1
								else:
													# connect nodes
													UpperCamelCase__		:    Any         =node
													UpperCamelCase__		:    Optional[Any]         =self._back
													UpperCamelCase__		:    str         =node  # assign new back to the new node

													self._len += 1

													# make sure there were no errors
													assert not self.is_empty(), "Error on appending value."






			def    _lowerCAmelCase			(							self     :					Optional[Any]						,  lowercase_     :					Any						):
								UpperCamelCase__		:    str         =self._Node(lowercase_						,  lowercase_						,  lowercase_						)
								if self.is_empty():
													# front = back
													UpperCamelCase__		:    str         =node
													UpperCamelCase__		:    Any         =1
								else:
													# connect nodes
													UpperCamelCase__		:    int         =self._front
													UpperCamelCase__		:    int         =node
													UpperCamelCase__		:    Any         =node  # assign new front to the new node

													self._len += 1

													# make sure there were no errors
													assert not self.is_empty(), "Error on appending value."






			def    _lowerCAmelCase			(							self     :					List[Any]						,  lowercase_     :					Iterable[Any]						):
								for val in iterable:
													self.append(lowercase_						)






			def    _lowerCAmelCase			(							self     :					Dict						,  lowercase_     :					Iterable[Any]						):
								for val in iterable:
													self.appendleft(lowercase_						)






			def    _lowerCAmelCase			(							self     :					Optional[int]						):
								assert not self.is_empty(), "Deque is empty."

								UpperCamelCase__		:    List[Any]         =self._back
								UpperCamelCase__		:    Any         =self._back.prev_node  # set new back
								# drop the last node - python will deallocate memory automatically
								UpperCamelCase__		:    List[str]         =None

								self._len -= 1

								return topop.val






			def    _lowerCAmelCase			(							self     :					str						):
								assert not self.is_empty(), "Deque is empty."

								UpperCamelCase__		:    List[str]         =self._front
								UpperCamelCase__		:    List[Any]         =self._front.next_node  # set new front and drop the first node
								UpperCamelCase__		:    Dict         =None

								self._len -= 1

								return topop.val






			def    _lowerCAmelCase			(							self     :					Dict						):
								return self._front is None






			def __len__(							self     :					Any						):
								return self._len






			def __eq__(							self     :					Dict						,  lowercase_     :					object						):

								if not isinstance(lowercase_						,  lowercase_						):
													return NotImplemented

								UpperCamelCase__		:    Union[str, Any]         =self._front
								UpperCamelCase__		:    Union[str, Any]         =other._front

								# if the length of the dequeues are not the same, they are not equal
								if len(self						) != len(lowercase_						):
													return False

								while me is not None and oth is not None:
													# compare every value
													if me.val != oth.val:
																		return False
													UpperCamelCase__		:    Union[str, Any]         =me.next_node
													UpperCamelCase__		:    Union[str, Any]         =oth.next_node

								return True






			def __iter__(							self     :					Optional[int]						):
								return Deque._Iterator(self._front						)






			def __repr__(							self     :					Tuple						):
								UpperCamelCase__		:    List[Any]         =[]
								UpperCamelCase__		:    Optional[int]         =self._front
								while aux is not None:
													# append the values in a list to display
													values_list.append(aux.val						)
													UpperCamelCase__		:    Optional[Any]         =aux.next_node

								return f'''[{', '.join(repr(lowercase_						) for val in values_list						)}]'''


if __name__ == "__main__":
				import doctest

				doctest.testmod()


