



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


_lowerCamelCase         =	"""none"""
_lowerCamelCase         =	"""none"""






def 						_lowerCAmelCase    (					__lowerCamelCase :  Any		,						__lowerCamelCase :  Dict  ):



 """simple docstring"""





 __SCREAMING_SNAKE_CASE							:     List[Any]							=						value.split(__lowerCamelCase  )
 return len(__lowerCamelCase  ) > 1 and any((len(__lowerCamelCase  ) == 3 for x in split)  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  Optional[int]  ):



 """simple docstring"""





 if isinstance(__lowerCamelCase		,						__lowerCamelCase  ):
  return value
 if isinstance(__lowerCamelCase		,						__lowerCamelCase  ):
  return float(__lowerCamelCase  )
 if not isinstance(__lowerCamelCase		,						__lowerCamelCase  ):
  raise ValueError("Argument value is not a string. Can't parse it as float"  )
 __SCREAMING_SNAKE_CASE							:     Optional[Any]							=						value

 try:
  # Example: 1,000.7
  if "." in sanitized and "," in sanitized:
   return float(sanitized.replace(","		,						""  )  )
  # 1,000
  if "," in sanitized and _split_thousands(","		,						__lowerCamelCase  ):
   return float(sanitized.replace(","		,						""  )  )
  # 5,5556
  if "," in sanitized and sanitized.count(","  ) == 1 and not _split_thousands(","		,						__lowerCamelCase  ):
   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(__lowerCamelCase  )
 except ValueError:
  # Avoid adding the sanitized value in the error message.
  raise ValueError("Unable to convert value to float"  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  Any  ):



 """simple docstring"""





 if answer is None:
  return None
 try:
  __SCREAMING_SNAKE_CASE							:     int							=						convert_to_float(__lowerCamelCase  )
  if isinstance(__lowerCamelCase		,						__lowerCamelCase  ) and math.isnan(__lowerCamelCase  ):
   return None
  return value
 except ValueError:
  return answer.lower()


_lowerCamelCase         =	{
    """text""": lambda x: x,
    """real""": convert_to_float,
}

class    _SCREAMING_SNAKE_CASE						(enum.Enum			):
     lowerCAmelCase       =      0
     lowerCAmelCase       =      1
     lowerCAmelCase       =      2
     lowerCAmelCase       =      3
     lowerCAmelCase       =      4
     lowerCAmelCase       =      5






class    _SCREAMING_SNAKE_CASE						(enum.Enum			):
     lowerCAmelCase       =      0
     lowerCAmelCase       =      1
     lowerCAmelCase       =      2






@dataclasses.dataclass
class    _SCREAMING_SNAKE_CASE						:
     lowerCAmelCase       =      42
     lowerCAmelCase       =      42
     lowerCAmelCase       =      42






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






def 						_lowerCAmelCase    (					__lowerCamelCase :  List[str]  ):



 """simple docstring"""





 return list(_TOKENIZER.findall(x.lower()  )  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  Dict		,						__lowerCamelCase :  Optional[int]		,						__lowerCamelCase :  Tuple  ):



 """simple docstring"""





 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 						_lowerCAmelCase    (					__lowerCamelCase :  List[Any]		,						__lowerCamelCase :  List[str]		,						__lowerCamelCase :  str  ):



 """simple docstring"""





 __SCREAMING_SNAKE_CASE							:     Union[str, Any]							=						table["types"]
 return _TYPE_CONVERTER[types[column]](__lowerCamelCase  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  Tuple  ):



 """simple docstring"""





 return isinstance(__lowerCamelCase		,						__lowerCamelCase  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  List[Any]		,						__lowerCamelCase :  Dict		,						__lowerCamelCase :  List[Any]  ):



 """simple docstring"""





 for cond in conditions:
  __SCREAMING_SNAKE_CASE							:     str							=						row[cond.column]

  __SCREAMING_SNAKE_CASE							:     str							=						_parse_value(__lowerCamelCase		,						cond.column		,						cond.cmp_value  )

  if _is_string(__lowerCamelCase  ) and _is_string(__lowerCamelCase  ):
   __SCREAMING_SNAKE_CASE							:     Tuple							=						_normalize_for_match(__lowerCamelCase  )
   __SCREAMING_SNAKE_CASE							:     str							=						_normalize_for_match(__lowerCamelCase  )

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

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






def 						_lowerCAmelCase    (					__lowerCamelCase :  List[str]		,						__lowerCamelCase :  Tuple		,						__lowerCamelCase :  Optional[Any]  ):



 """simple docstring"""





 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(__lowerCamelCase  )  )

 # If we have just one answer, if float returns it or try a conversion.
 __SCREAMING_SNAKE_CASE							:     Optional[int]							=						[table["rows"][i][j] for (i, j) in answer_coordinates]
 if len(__lowerCamelCase  ) == 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(__lowerCamelCase		,						(int, float)  ) for v in values)  ):
  return None

 if aggregation_op == _Aggregation.SUM:
  return float(sum(__lowerCamelCase  )  )
 elif aggregation_op == _Aggregation.AVERAGE:
  return sum(__lowerCamelCase  ) / len(__lowerCamelCase  )
 else:
  raise ValueError(F"""Unknown aggregation: {aggregation_op}"""  )






def 						_lowerCAmelCase    (					__lowerCamelCase :  List[str]		,						__lowerCamelCase :  Tuple  ):



 """simple docstring"""





 __SCREAMING_SNAKE_CASE							:     Optional[int]							=						sql_query["agg"]
 if aggregation_op_index >= 3:
  __SCREAMING_SNAKE_CASE							:     List[str]							=						_Aggregation(__lowerCamelCase  )
 else:
  __SCREAMING_SNAKE_CASE							:     List[str]							=						_Aggregation.NONE

 __SCREAMING_SNAKE_CASE							:     Dict							=						sql_query["sel"]
 __SCREAMING_SNAKE_CASE							:     Optional[Any]							=						[
     _Condition(__lowerCamelCase		,						_Operator(__lowerCamelCase  )		,						__lowerCamelCase  )
     for column, operator, cmp_value in zip(
         sql_query["conds"]["column_index"]		,						sql_query["conds"]["operator_index"]		,						sql_query["conds"]["condition"]  )
 ]

 __SCREAMING_SNAKE_CASE							:     Tuple							=						[]
 for row in range(len(table["rows"]  )  ):
  if _respect_conditions(__lowerCamelCase		,						table["rows"][row]		,						__lowerCamelCase  ):
   indices.append((row, target_column)  )

 if not indices:
  return [], aggregation_op

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

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

  __SCREAMING_SNAKE_CASE							:     Dict							=						[indices[reduced[1]]]
  return ret, _Aggregation.NONE

 return indices, aggregation_op






def 						_lowerCAmelCase    (					__lowerCamelCase :  Optional[Any]		,						__lowerCamelCase :  List[str]		,						__lowerCamelCase :  List[Any]  ):



 """simple docstring"""





 if float_answer is not None:
  return [str(__lowerCamelCase  )]
 return [str(table["real_rows"][r][c]  ) for r, c in answer_coordinates]






def 						_lowerCAmelCase    (					__lowerCamelCase :  List[str]		,						__lowerCamelCase :  Optional[Any]  ):



 """simple docstring"""





 __SCREAMING_SNAKE_CASE,		__SCREAMING_SNAKE_CASE							:     Dict							=						_get_answer_coordinates(__lowerCamelCase		,						__lowerCamelCase  )
 __SCREAMING_SNAKE_CASE							:     Dict							=						_get_float_answer(__lowerCamelCase		,						__lowerCamelCase		,						__lowerCamelCase  )
 __SCREAMING_SNAKE_CASE							:     Optional[Any]							=						_get_answer_text(__lowerCamelCase		,						__lowerCamelCase		,						__lowerCamelCase  )
 # keep the original data the same with TaPas
 if len(__lowerCamelCase  ) == 0:
  __SCREAMING_SNAKE_CASE							:     Any							=						[EMPTY_ANSWER]
 return answer_text










def 		_UpperCAmelCase							(     SCREAMING_SNAKE_CASE__     :   list     ,	SCREAMING_SNAKE_CASE__     :   int     ,	SCREAMING_SNAKE_CASE__     :   int     ,	SCREAMING_SNAKE_CASE__     :   int							):
     __UpperCamelCase       				=int((lower_bound + upper_bound) // 2							)
     if array[r] == value:
          return r
     if lower_bound >= upper_bound:
          return -1
     if array[r] < value:
          return binary_search(SCREAMING_SNAKE_CASE__     ,	r + 1     ,	SCREAMING_SNAKE_CASE__     ,	SCREAMING_SNAKE_CASE__							)
     else:
          return binary_search(SCREAMING_SNAKE_CASE__     ,	SCREAMING_SNAKE_CASE__     ,	r - 1     ,	SCREAMING_SNAKE_CASE__							)

def 		_UpperCAmelCase							(     SCREAMING_SNAKE_CASE__     :   int     ,	SCREAMING_SNAKE_CASE__     :   list							):
     __UpperCamelCase       				=0
     if matrix[index][0] == value:
          return [index, 0]
     while index < len(SCREAMING_SNAKE_CASE__							) and matrix[index][0] < value:
          __UpperCamelCase       				=binary_search(matrix[index]     ,	0     ,	len(matrix[index]							) - 1     ,	SCREAMING_SNAKE_CASE__							)
          if r != -1:
               return [index, r]
          index += 1
     return [-1, -1]


if __name__ == "__main__":
   import doctest

   doctest.testmod()





