'''simple docstring'''




from __future__ import annotations

import time
from math import sqrt

# 1 for manhattan, 0 for euclidean
_UpperCamelCase					:		List[Any]							      =		0

_UpperCamelCase					:		Union[str, Any]							      =		[
    [0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 0, 0, 0],  # 0 are free path whereas 1's are obstacles
    [0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0],
    [1, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0],
]

_UpperCamelCase					:		List[Any]							      =		[[-1, 0], [0, -1], [1, 0], [0, 1]]  # up, left, down, right

_UpperCamelCase					:		List[str]							      =		tuple[int, int]

class 	_lowercase:



   """simple docstring"""





   def __init__(				self:     List[str]      ,a:     Dict      ,a:     str      ,a:     List[Any]      ,a:     Dict      ,a:     List[Any]      ,a:     str      ,):
    __UpperCAmelCase								=       pos_x
    __UpperCAmelCase								=       pos_y
    __UpperCAmelCase								=       (pos_y, pos_x)
    __UpperCAmelCase								=       goal_x
    __UpperCAmelCase								=       goal_y
    __UpperCAmelCase								=       g_cost
    __UpperCAmelCase								=       parent
    __UpperCAmelCase								=       self.calculate_heuristic()
    __UpperCAmelCase								=       self.g_cost + self.h_cost





   def       snake_case						(				self:     Optional[Any]						):
    __UpperCAmelCase								=       self.pos_x - self.goal_x
    __UpperCAmelCase								=       self.pos_y - self.goal_y
    if HEURISTIC == 1:
     return abs(lowerCAmelCase__						) + abs(lowerCAmelCase__						)
    else:
     return sqrt(dy**2 + dx**2						)





   def __lt__(				self:     Tuple      ,a:     Dict						):
    return self.f_cost < other.f_cost




class 	_lowercase:



   """simple docstring"""





   def __init__(				self:     int      ,a:     Union[str, Any]      ,a:     Any						):
    __UpperCAmelCase								=       Node(start[1]      ,start[0]      ,goal[1]      ,goal[0]      ,0      ,lowerCAmelCase__						)
    __UpperCAmelCase								=       Node(goal[1]      ,goal[0]      ,goal[1]      ,goal[0]      ,99999      ,lowerCAmelCase__						)

    __UpperCAmelCase								=       [self.start]
    __UpperCAmelCase								=       []

    __UpperCAmelCase								=       False





   def       snake_case						(				self:     Optional[int]						):


    while self.open_nodes:
     # Open Nodes are sorted using __lt__
     self.open_nodes.sort()
     __UpperCAmelCase								=       self.open_nodes.pop(0						)

     if current_node.pos == self.target.pos:
      return self.retrace_path(lowerCAmelCase__						)

     self.closed_nodes.append(lowerCAmelCase__						)
     __UpperCAmelCase								=       self.get_successors(lowerCAmelCase__						)

     for child_node in successors:
      if child_node in self.closed_nodes:
       continue

      if child_node not in self.open_nodes:
       self.open_nodes.append(lowerCAmelCase__						)
      else:
       # retrieve the best current path
       __UpperCAmelCase								=       self.open_nodes.pop(self.open_nodes.index(lowerCAmelCase__						)						)

       if child_node.g_cost < better_node.g_cost:
        self.open_nodes.append(lowerCAmelCase__						)
       else:
        self.open_nodes.append(lowerCAmelCase__						)

    return [self.start.pos]





   def       snake_case						(				self:     Optional[int]      ,a:     List[Any]						):
    __UpperCAmelCase								=       []
    for action in delta:
     __UpperCAmelCase								=       parent.pos_x + action[1]
     __UpperCAmelCase								=       parent.pos_y + action[0]
     if not (0 <= pos_x <= len(grid[0]						) - 1 and 0 <= pos_y <= len(lowerCAmelCase__						) - 1):
      continue

     if grid[pos_y][pos_x] != 0:
      continue

     successors.append(
         Node(
             lowerCAmelCase__      ,lowerCAmelCase__      ,self.target.pos_y      ,self.target.pos_x      ,parent.g_cost + 1      ,lowerCAmelCase__      ,)						)
    return successors





   def       snake_case						(				self:     Any      ,a:     int						):
    __UpperCAmelCase								=       node
    __UpperCAmelCase								=       []
    while current_node is not None:
     path.append((current_node.pos_y, current_node.pos_x)						)
     __UpperCAmelCase								=       current_node.parent
    path.reverse()
    return path




class 	_lowercase:



   """simple docstring"""





   def __init__(				self:     Tuple      ,a:     Tuple      ,a:     Dict						):
    __UpperCAmelCase								=       AStar(lowerCAmelCase__      ,lowerCAmelCase__						)
    __UpperCAmelCase								=       AStar(lowerCAmelCase__      ,lowerCAmelCase__						)
    __UpperCAmelCase								=       False





   def       snake_case						(				self:     Optional[Any]						):


    while self.fwd_astar.open_nodes or self.bwd_astar.open_nodes:
     self.fwd_astar.open_nodes.sort()
     self.bwd_astar.open_nodes.sort()
     __UpperCAmelCase								=       self.fwd_astar.open_nodes.pop(0						)
     __UpperCAmelCase								=       self.bwd_astar.open_nodes.pop(0						)

     if current_bwd_node.pos == current_fwd_node.pos:
      return self.retrace_bidirectional_path(
          lowerCAmelCase__      ,lowerCAmelCase__						)

     self.fwd_astar.closed_nodes.append(lowerCAmelCase__						)
     self.bwd_astar.closed_nodes.append(lowerCAmelCase__						)

     __UpperCAmelCase								=       current_bwd_node
     __UpperCAmelCase								=       current_fwd_node

     __UpperCAmelCase								=       {
         self.fwd_astar: self.fwd_astar.get_successors(lowerCAmelCase__						),
         self.bwd_astar: self.bwd_astar.get_successors(lowerCAmelCase__						),
     }

     for astar in [self.fwd_astar, self.bwd_astar]:
      for child_node in successors[astar]:
       if child_node in astar.closed_nodes:
        continue

       if child_node not in astar.open_nodes:
        astar.open_nodes.append(lowerCAmelCase__						)
       else:
        # retrieve the best current path
        __UpperCAmelCase								=       astar.open_nodes.pop(
            astar.open_nodes.index(lowerCAmelCase__						)						)

        if child_node.g_cost < better_node.g_cost:
         astar.open_nodes.append(lowerCAmelCase__						)
        else:
         astar.open_nodes.append(lowerCAmelCase__						)

    return [self.fwd_astar.start.pos]





   def       snake_case						(				self:     Optional[Any]      ,a:     Optional[int]      ,a:     Tuple						):
    __UpperCAmelCase								=       self.fwd_astar.retrace_path(lowerCAmelCase__						)
    __UpperCAmelCase								=       self.bwd_astar.retrace_path(lowerCAmelCase__						)
    bwd_path.pop()
    bwd_path.reverse()
    __UpperCAmelCase								=       fwd_path + bwd_path
    return path


if __name__ == "__main__":
     # all coordinates are given in format [y,x]
     _UpperCamelCase					:		Any							      =		(0, 0)
     _UpperCamelCase					:		Any							      =		(len(grid) - 1, len(grid[0]) - 1)
     for elem in grid:
          print(elem)

     _UpperCamelCase					:		Optional[Any]							      =		time.time()
     _UpperCamelCase					:		Optional[Any]							      =		AStar(init, goal)
     _UpperCamelCase					:		str							      =		a_star.search()
     _UpperCamelCase					:		List[Any]							      =		time.time() - start_time
     print(f"AStar execution time = {end_time:f} seconds")

     _UpperCamelCase					:		int							      =		time.time()
     _UpperCamelCase					:		List[Any]							      =		BidirectionalAStar(init, goal)
     _UpperCamelCase					:		Tuple							      =		time.time() - bd_start_time
     print(f"BidirectionalAStar execution time = {bd_end_time:f} seconds")




import sys
import webbrowser

import requests
from bsa import BeautifulSoup
from fake_useragent import UserAgent

if __name__ == "__main__":
		print("""Googling.....""")
		__a    :	Tuple         =    """https://www.google.com/search?q=""" + """ """.join(sys.argv[1:])
		__a    :	List[str]         =    requests.get(url, headers={"""UserAgent""": UserAgent().random})
		# res.raise_for_status()
		with open("""project1a.html""", """wb""") as out_file:  # only for knowing the class
				for data in res.iter_content(1_0_0_0_0):
						out_file.write(data)
		__a    :	Dict         =    BeautifulSoup(res.text, """html.parser""")
		__a    :	Any         =    list(soup.select(""".eZt8xd"""))[:5]

		print(len(links))
		for link in links:
				if link.text == "Maps":
						webbrowser.open(link.get("""href"""))
				else:
						webbrowser.open(F'''https://google.com{link.get("href")}''')