import dataclasses
import enum
import functools
import math
import re

# The following script is adapted from the script of TaPas.
# Original: https://github.com/google-research/tapas/master/wikisql_utils.py
from typing import Any, List, Text


_snake_case			=						'''none'''
_snake_case			=						'''none'''




def   _UpperCamelCase   (			snake_case__,    snake_case__							)						->   int:
							__UpperCAmelCase						:			int         =   value.split(snake_case__							)
							return len(snake_case__							) > 1 and any((len(snake_case__							) == 3 for x in split)							)




def   _UpperCamelCase   (			snake_case__							)						->   Optional[int]:
							if isinstance(snake_case__,    snake_case__							):
														return value
							if isinstance(snake_case__,    snake_case__							):
														return float(snake_case__							)
							if not isinstance(snake_case__,    snake_case__							):
														raise ValueError("Argument value is not a string. Can't parse it as float"							)
							__UpperCAmelCase						:			Tuple         =   value

							try:
														# Example: 1,000.7
														if "." in sanitized and "," in sanitized:
																					return float(sanitized.replace(",",    ""							)							)
														# 1,000
														if "," in sanitized and _split_thousands(",",    snake_case__							):
																					return float(sanitized.replace(",",    ""							)							)
														# 5,5556
														if "," in sanitized and sanitized.count(","							) == 1 and not _split_thousands(",",    snake_case__							):
																					return float(sanitized.replace(",",    "."							)							)
														# 0.0.0.1
														if sanitized.count("."							) > 1:
																					return float(sanitized.replace(".",    ""							)							)
														# 0,0,0,1
														if sanitized.count(","							) > 1:
																					return float(sanitized.replace(",",    ""							)							)
														return float(snake_case__							)
							except ValueError:
														# Avoid adding the sanitized value in the error message.
														raise ValueError("Unable to convert value to float"							)




def   _UpperCamelCase   (			snake_case__							)						->   Optional[int]:
							if answer is None:
														return None
							try:
														__UpperCAmelCase						:			int         =   convert_to_float(snake_case__							)
														if isinstance(snake_case__,    snake_case__							) and math.isnan(snake_case__							):
																					return None
														return value
							except ValueError:
														return answer.lower()


_snake_case			=						{
    '''text''': lambda x: x,
    '''real''': convert_to_float,
}




class 					_snake_case						(						enum.Enum				):
					lowerCamelCase__:		Dict  =     0
					lowerCamelCase__:		Optional[Any]  =     1
					lowerCamelCase__:		Tuple  =     2
					lowerCamelCase__:		Optional[Any]  =     3
					lowerCamelCase__:		List[str]  =     4
					lowerCamelCase__:		Tuple  =     5




class 					_snake_case						(						enum.Enum				):
					lowerCamelCase__:		Tuple  =     0
					lowerCamelCase__:		List[str]  =     1
					lowerCamelCase__:		List[str]  =     2




@dataclasses.dataclass
class 					_snake_case						:
					lowerCamelCase__:		Text
					lowerCamelCase__:		_Operator
					lowerCamelCase__:		Any




_snake_case			=						re.compile(r'''\w+|[^\w\s]+''', re.UNICODE | re.MULTILINE | re.DOTALL)




def   _UpperCamelCase   (			snake_case__							)						->   List[Any]:
							return list(_TOKENIZER.findall(x.lower()							)							)




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   Dict:
							if operator == _Operator.EQUALS:
														return src == tgt
							elif operator == _Operator.GREATER:
														return src > tgt
							elif operator == _Operator.LESSER:
														return src < tgt
							raise ValueError(f'''Unknown operator: {operator}'''							)




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   List[Any]:
							__UpperCAmelCase						:			Optional[int]         =   table["types"]
							return _TYPE_CONVERTER[types[column]](snake_case__							)




def   _UpperCamelCase   (			snake_case__							)						->   Union[str, Any]:
							return isinstance(snake_case__,    snake_case__							)




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   Optional[int]:
							for cond in conditions:
														__UpperCAmelCase						:			List[str]         =   row[cond.column]

														__UpperCAmelCase						:			Tuple         =   _parse_value(snake_case__,    cond.column,    cond.cmp_value							)

														if _is_string(snake_case__							) and _is_string(snake_case__							):
																					__UpperCAmelCase						:			Union[str, Any]         =   _normalize_for_match(snake_case__							)
																					__UpperCAmelCase						:			str         =   _normalize_for_match(snake_case__							)

														if not isinstance(snake_case__,    type(snake_case__							)							):
																					raise ValueError("Type difference {} != {}".format(type(snake_case__							),    type(snake_case__							)							)							)

														if not _compare(cond.operator,    snake_case__,    snake_case__							):
																					return False
							return True




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   Dict:
							if not answer_coordinates:
														if aggregation_op == _Aggregation.COUNT:
																					return 0.0
														else:
																					return EMPTY_ANSWER_AGG

    # Count can support non numeric answers.
							if aggregation_op == _Aggregation.COUNT:
														return float(len(snake_case__							)							)

							# If we have just one answer, if float returns it or try a conversion.
							__UpperCAmelCase						:			List[str]         =   [table["rows"][i][j] for (i, j) in answer_coordinates]
							if len(snake_case__							) == 1:
														try:
																					return convert_to_float(values[0]							)
														except ValueError as e:
																					if aggregation_op != _Aggregation.NONE:
																												raise e

							if aggregation_op == _Aggregation.NONE:
														return None

							# Other aggregation only support numeric values. Bail out if we have strings.
							if not all((isinstance(snake_case__,    (int, float)							) for v in values)							):
														return None

							if aggregation_op == _Aggregation.SUM:
														return float(sum(snake_case__							)							)
							elif aggregation_op == _Aggregation.AVERAGE:
														return sum(snake_case__							) / len(snake_case__							)
							else:
														raise ValueError(f'''Unknown aggregation: {aggregation_op}'''							)




def   _UpperCamelCase   (			snake_case__,    snake_case__							)						->   Union[str, Any]:
							__UpperCAmelCase						:			str         =   sql_query["agg"]
							if aggregation_op_index >= 3:
														__UpperCAmelCase						:			int         =   _Aggregation(snake_case__							)
							else:
														__UpperCAmelCase						:			int         =   _Aggregation.NONE

							__UpperCAmelCase						:			List[str]         =   sql_query["sel"]
							__UpperCAmelCase						:			Any         =   [
							    _Condition(snake_case__,    _Operator(snake_case__							),    snake_case__							)
							    for column, operator, cmp_value in zip(
							        sql_query["conds"]["column_index"],    sql_query["conds"]["operator_index"],    sql_query["conds"]["condition"]							)
							]

							__UpperCAmelCase						:			Union[str, Any]         =   []
							for row in range(len(table["rows"]							)							):
														if _respect_conditions(snake_case__,    table["rows"][row],    snake_case__							):
																					indices.append((row, target_column)							)

							if not indices:
														return [], aggregation_op

							if len(snake_case__							) == 1:
														return indices, aggregation_op

							# Parsing of MIN/MAX.
							if aggregation_op_index in (1, 2):
														__UpperCAmelCase						:			Optional[Any]         =   {2: min, 1: max}
														__UpperCAmelCase						:			int         =   [(table["rows"][i][j], index) for index, (i, j) in enumerate(snake_case__							)]
														__UpperCAmelCase						:			Optional[int]         =   functools.reduce(operators[sql_query["agg"]],    snake_case__							)

														__UpperCAmelCase						:			Any         =   [indices[reduced[1]]]
														return ret, _Aggregation.NONE

							return indices, aggregation_op




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   Any:
							if float_answer is not None:
														return [str(snake_case__							)]
							return [str(table["real_rows"][r][c]							) for r, c in answer_coordinates]







def   _UpperCamelCase   (			snake_case__,    snake_case__							)						->   List:
							__UpperCAmelCase    ,	__UpperCAmelCase						:			Optional[int]         =   _get_answer_coordinates(snake_case__,    snake_case__							)
							__UpperCAmelCase						:			Optional[int]         =   _get_float_answer(snake_case__,    snake_case__,    snake_case__							)
							__UpperCAmelCase						:			Optional[int]         =   _get_answer_text(snake_case__,    snake_case__,    snake_case__							)
							# keep the original data the same with TaPas
							if len(snake_case__							) == 0:
														__UpperCAmelCase						:			Dict         =   [EMPTY_ANSWER]
							return answer_text





from __future__ import annotations

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




class 					_snake_case						(						_lowercase				):
					lowerCamelCase__:		Tuple  =     1
					lowerCamelCase__:		Dict  =     2
					lowerCamelCase__:		List[str]  =     3
					def __repr__(  self:				List[Any]     )    ->				int:
												return f'''{self.__class__.__name__}.{self.name}'''




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   float:
							__UpperCAmelCase    ,	__UpperCAmelCase						:			Optional[Any]         =   point
							return degrees(atana(y - miny,    x - minx							)							)




def   _UpperCamelCase   (			snake_case__,    snake_case__,    snake_case__							)						->   Direction:
							__UpperCAmelCase    ,	__UpperCAmelCase						:			List[Any]         =   starting
							__UpperCAmelCase    ,	__UpperCAmelCase						:			Optional[int]         =   via
							__UpperCAmelCase    ,	__UpperCAmelCase						:			List[str]         =   target
							__UpperCAmelCase						:			Tuple         =   degrees(atana(ya - ya,    xa - xa							)							)
							via_angle %= 360
							__UpperCAmelCase						:			str         =   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   _UpperCamelCase   (			snake_case__							)						->   list[tuple[int, int]]:

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

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

							__UpperCAmelCase						:			Any         =   sorted(snake_case__,    key=lambda snake_case__							: angle_comparer(snake_case__,    snake_case__,    snake_case__							)							)
							# 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						:			Any         =   Direction.left

							for i in range(3,    len(snake_case__							)							):
														while True:
																					__UpperCAmelCase						:			List[Any]         =   stack[-2]
																					__UpperCAmelCase						:			Tuple         =   stack[-1]
																					__UpperCAmelCase						:			Any         =   sorted_points[i]
																					__UpperCAmelCase						:			Optional[Any]         =   check_direction(snake_case__,    snake_case__,    snake_case__							)

																					if next_direction == Direction.left:
																												__UpperCAmelCase						:			Optional[int]         =   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(snake_case__							)




