
import heapq
import sys

import numpy as np

lowercase  :					List[Any]													=       tuple[int, int]




class  lowerCamelCase__							:




	'''simple docstring'''




	def __init__(					self		:Any						)		-> List[str]:
								__UpperCamelCase	:   str			   =					[]
								__UpperCamelCase	:   List[Any]			   =					set()







	def    _lowerCamelCase				(					self		:int						)		-> Tuple:
								if not self.empty():
															return self.elements[0][0]
								else:
															return float("inf"						)







	def    _lowerCamelCase				(					self		:Dict						)		-> List[Any]:
								return len(self.elements						) == 0







	def    _lowerCamelCase				(					self		:Any     ,   a		:Optional[Any]     ,   a		:Union[str, Any]						)		-> Any:
								if item not in self.set:
															heapq.heappush(self.elements     ,   (priority, item)						)
															self.set.add(a						)
								else:
															# update
															# print("update", item)
															__UpperCamelCase	:   Dict			   =					[]
															((__UpperCamelCase)   ,						(__UpperCamelCase))	:   Any			   =					heapq.heappop(self.elements						)
															while x != item:
																						temp.append((pri, x)						)
																						((__UpperCamelCase)   ,						(__UpperCamelCase))	:   Optional[int]			   =					heapq.heappop(self.elements						)
															temp.append((priority, item)						)
															for pro, xxx in temp:
																						heapq.heappush(self.elements     ,   (pro, xxx)						)







	def    _lowerCamelCase				(					self		:Union[str, Any]     ,   a		:int						)		-> List[Any]:
								if item in self.set:
															self.set.remove(a						)
															__UpperCamelCase	:   Dict			   =					[]
															((__UpperCamelCase)   ,						(__UpperCamelCase))	:   str			   =					heapq.heappop(self.elements						)
															while x != item:
																						temp.append((pro, x)						)
																						((__UpperCamelCase)   ,						(__UpperCamelCase))	:   List[Any]			   =					heapq.heappop(self.elements						)
															for prito, yyy in temp:
																						heapq.heappush(self.elements     ,   (prito, yyy)						)







	def    _lowerCamelCase				(					self		:str						)		-> Optional[int]:
								return self.elements[0][1]







	def    _lowerCamelCase				(					self		:Tuple						)		-> List[Any]:
								((__UpperCamelCase)   ,						(__UpperCamelCase))	:   Union[str, Any]			   =					heapq.heappop(self.elements						)
								self.set.remove(a						)
								return (priority, item)




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos						,  _lowerCamelCase :			TPos)					->    Optional[Any]:






							'''simple docstring'''





							__UpperCamelCase	:   Any			   =					np.array(_lowerCamelCase)
							__UpperCamelCase	:   str			   =					np.array(_lowerCamelCase)
							return np.linalg.norm(a - b)




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos						,  _lowerCamelCase :			TPos)					->    Union[str, Any]:






							'''simple docstring'''





							return consistent_heuristic(_lowerCamelCase						,  _lowerCamelCase) // t




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos						,  _lowerCamelCase :			TPos)					->    Any:






							'''simple docstring'''





							return abs(p[0] - goal[0]) + abs(p[1] - goal[1])




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos						,  _lowerCamelCase :			int						,  _lowerCamelCase :			TPos						,  _lowerCamelCase :			dict[TPos, float])					->    Union[str, Any]:






							'''simple docstring'''





							__UpperCamelCase	:   Optional[int]			   =					g_function[start] + Wa * heuristics[i](_lowerCamelCase						,  _lowerCamelCase)
							return ans




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			Optional[Any]						,  _lowerCamelCase :			List[str]						,  _lowerCamelCase :			int)					->    Optional[Any]:






							'''simple docstring'''





							__UpperCamelCase	:   int			   =					np.chararray((n, n))
							for i in range(_lowerCamelCase):
														for j in range(_lowerCamelCase):
																					__UpperCamelCase	:   Dict			   =					"*"

							for i in range(_lowerCamelCase):
														for j in range(_lowerCamelCase):
																					if (j, (n - 1) - i) in blocks:
																												__UpperCamelCase	:   Optional[int]			   =					"#"

							__UpperCamelCase	:   List[Any]			   =					"-"
							__UpperCamelCase	:   Optional[int]			   =					back_pointer[goal]
							while x != start:
														((__UpperCamelCase)   ,						(__UpperCamelCase))	:   List[Any]			   =					x
														# print(x)
														__UpperCamelCase	:   int			   =					"-"
														__UpperCamelCase	:   List[str]			   =					back_pointer[x]
							__UpperCamelCase	:   Optional[int]			   =					"-"

							for i in range(_lowerCamelCase):
														for j in range(_lowerCamelCase):
																					if (i, j) == (0, n - 1):
																												print(grid[i][j]						,  end=" ")
																												print("<-- End position"						,  end=" ")
																					else:
																												print(grid[i][j]						,  end=" ")
														print()
							print("^")
							print("Start position")
							print()
							print("# is an obstacle")
							print("- is the path taken by algorithm")
							print("PATH TAKEN BY THE ALGORITHM IS:-")
							__UpperCamelCase	:   Optional[int]			   =					back_pointer[goal]
							while x != start:
														print(_lowerCamelCase						,  end=" ")
														__UpperCamelCase	:   Any			   =					back_pointer[x]
							print(_lowerCamelCase)
							sys.exit()




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos)					->    Any:






							'''simple docstring'''





							if p[0] < 0 or p[0] > n - 1:
														return False
							if p[1] < 0 or p[1] > n - 1:
														return False
							return True




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			Optional[Any]						,  _lowerCamelCase :			Dict						,  _lowerCamelCase :			Union[str, Any]						,  _lowerCamelCase :			str						,  _lowerCamelCase :			str						,  _lowerCamelCase :			Any						,  _lowerCamelCase :			Any						,  _lowerCamelCase :			Optional[int]						,  )					->    int:






							'''simple docstring'''





							for itera in range(_lowerCamelCase):
														open_list[itera].remove_element(_lowerCamelCase)
							# print("s", s)
							# print("j", j)
							((__UpperCamelCase)   ,						(__UpperCamelCase))	:   int			   =					s
							__UpperCamelCase	:   int			   =					(x - 1, y)
							__UpperCamelCase	:   Dict			   =					(x + 1, y)
							__UpperCamelCase	:   Any			   =					(x, y + 1)
							__UpperCamelCase	:   Union[str, Any]			   =					(x, y - 1)

							for neighbours in [left, right, up, down]:
														if neighbours not in blocks:
																					if valid(_lowerCamelCase) and neighbours not in visited:
																												# print("neighbour", neighbours)
																												visited.add(_lowerCamelCase)
																												__UpperCamelCase	:   List[Any]			   =					-1
																												__UpperCamelCase	:   Optional[Any]			   =					float("inf")

																					if valid(_lowerCamelCase) and g_function[neighbours] > g_function[s] + 1:
																												__UpperCamelCase	:   Union[str, Any]			   =					g_function[s] + 1
																												__UpperCamelCase	:   List[str]			   =					s
																												if neighbours not in close_list_anchor:
																																			open_list[0].put(_lowerCamelCase						,  key(_lowerCamelCase						,  0						,  _lowerCamelCase						,  _lowerCamelCase))
																																			if neighbours not in close_list_inad:
																																										for var in range(1						,  _lowerCamelCase):
																																																	if key(_lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase) <= Wa * key(
																																																	    _lowerCamelCase						,  0						,  _lowerCamelCase						,  _lowerCamelCase):
																																																								open_list[j].put(
																																																								    _lowerCamelCase						,  key(_lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase))




def 	_SCREAMING_SNAKE_CASE					(		)					->    str:






							'''simple docstring'''





							__UpperCamelCase	:   Optional[int]			   =					[]
							for x in range(1						,  5):
														for y in range(1						,  6):
																					some_list.append((x, y))

							for x in range(15						,  20):
														some_list.append((x, 17))

							for x in range(10						,  19):
														for y in range(1						,  15):
																					some_list.append((x, y))

    # L block
							for x in range(1						,  4):
														for y in range(12						,  19):
																					some_list.append((x, y))
							for x in range(3						,  13):
														for y in range(16						,  19):
																					some_list.append((x, y))
							return some_list


lowercase  :					Any													=       {0: consistent_heuristic, 1: heuristic_a, 2: heuristic_a}

lowercase  :					List[str]													=       [
    (0, 1),
    (1, 1),
    (2, 1),
    (3, 1),
    (4, 1),
    (5, 1),
    (6, 1),
    (7, 1),
    (8, 1),
    (9, 1),
    (10, 1),
    (11, 1),
    (12, 1),
    (13, 1),
    (14, 1),
    (15, 1),
    (16, 1),
    (17, 1),
    (18, 1),
    (19, 1),
]
lowercase  :					List[str]													=       make_common_ground()


lowercase  :					int													=       blocks_blk
# hyper parameters
lowercase  :					List[str]													=       1
lowercase  :					Tuple													=       1
lowercase  :					List[Any]													=       20
lowercase  :					int													=       3  # one consistent and two other inconsistent

# start and end destination
lowercase  :					Dict													=       (0, 0)
lowercase  :					Any													=       (n - 1, n - 1)

lowercase  :					List[Any]													=       1




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			TPos						,  _lowerCamelCase :			TPos						,  _lowerCamelCase :			int)					->    Dict:






							'''simple docstring'''





							__UpperCamelCase	:   Optional[int]			   =					{start: 0, goal: float("inf")}
							__UpperCamelCase	:   str			   =					{start: -1, goal: -1}
							__UpperCamelCase	:   Optional[int]			   =					[]
							__UpperCamelCase	:   List[Any]			   =					set()

							for i in range(_lowerCamelCase):
														open_list.append(PriorityQueue())
														open_list[i].put(_lowerCamelCase						,  key(_lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase))

							__UpperCamelCase	:   list[int]			   =					[]
							__UpperCamelCase	:   list[int]			   =					[]
							while open_list[0].minkey() < float("inf"):
														for i in range(1						,  _lowerCamelCase):
																					# print(open_list[0].minkey(), open_list[i].minkey())
																					if open_list[i].minkey() <= Wa * open_list[0].minkey():
																												global t
																												t += 1
																												if g_function[goal] <= open_list[i].minkey():
																																			if g_function[goal] < float("inf"):
																																										do_something(_lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase)
																												else:
																																			__UpperCamelCase   ,						__UpperCamelCase	:   int			   =					open_list[i].top_show()
																																			visited.add(_lowerCamelCase)
																																			expand_state(
																																			    _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  )
																																			close_list_inad.append(_lowerCamelCase)
																					else:
																												if g_function[goal] <= open_list[0].minkey():
																																			if g_function[goal] < float("inf"):
																																										do_something(_lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase)
																												else:
																																			__UpperCamelCase	:   List[Any]			   =					open_list[0].top_show()
																																			visited.add(_lowerCamelCase)
																																			expand_state(
																																			    _lowerCamelCase						,  0						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  _lowerCamelCase						,  )
																																			close_list_anchor.append(_lowerCamelCase)
							print("No path found to goal")
							print()
							for i in range(n - 1						,  -1						,  -1):
														for j in range(_lowerCamelCase):
																					if (j, i) in blocks:
																												print("#"						,  end=" ")
																					elif (j, i) in back_pointer:
																												if (j, i) == (n - 1, n - 1):
																																			print("*"						,  end=" ")
																												else:
																																			print("-"						,  end=" ")
																					else:
																												print("*"						,  end=" ")
																					if (j, i) == (n - 1, n - 1):
																												print("<-- End position"						,  end=" ")
														print()
							print("^")
							print("Start position")
							print()
							print("# is an obstacle")
							print("- is the path taken by algorithm")


if __name__ == "__main__":
		multi_a_star(start, goal, n_heuristic)

from __future__ import annotations




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			list[list[int]])					->    bool:






							'''simple docstring'''





							__UpperCamelCase	:   Any			   =					len(_lowerCamelCase)
							# We need to create solution object to save path.
							__UpperCamelCase	:   List[str]			   =					[[0 for _ in range(_lowerCamelCase)] for _ in range(_lowerCamelCase)]
							__UpperCamelCase	:   Optional[int]			   =					run_maze(_lowerCamelCase						,  0						,  0						,  _lowerCamelCase)
							if solved:
														print("\n".join(str(_lowerCamelCase) for row in solutions))
							else:
														print("No solution exists!")
							return solved




def 	_SCREAMING_SNAKE_CASE					(		_lowerCamelCase :			list[list[int]]						,  _lowerCamelCase :			int						,  _lowerCamelCase :			int						,  _lowerCamelCase :			list[list[int]])					->    bool:






							'''simple docstring'''





							__UpperCamelCase	:   Tuple			   =					len(_lowerCamelCase)
							# Final check point.
							if i == j == (size - 1):
														__UpperCamelCase	:   Optional[int]			   =					1
														return True

							__UpperCamelCase	:   List[Any]			   =					(not i < 0) and (not j < 0)  # Check lower bounds
							__UpperCamelCase	:   List[str]			   =					(i < size) and (j < size)  # Check upper bounds

							if lower_flag and upper_flag:
														# check for already visited and block points.
														__UpperCamelCase	:   int			   =					(not solutions[i][j]) and (not maze[i][j])
														if block_flag:
																					# check visited
																					__UpperCamelCase	:   Tuple			   =					1

																					# check for directions
																					if (
																					    run_maze(_lowerCamelCase						,  i + 1						,  _lowerCamelCase						,  _lowerCamelCase)
																					    or run_maze(_lowerCamelCase						,  _lowerCamelCase						,  j + 1						,  _lowerCamelCase)
																					    or run_maze(_lowerCamelCase						,  i - 1						,  _lowerCamelCase						,  _lowerCamelCase)
																					    or run_maze(_lowerCamelCase						,  _lowerCamelCase						,  j - 1						,  _lowerCamelCase)
																					):
																												return True

																					__UpperCamelCase	:   Tuple			   =					0
																					return False
							return False


if __name__ == "__main__":
		import doctest

		doctest.testmod()