



from __future__ import annotations

import time

A__	      =       list[tuple[int, int]]

A__	      =       [
    [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],
]

A__	      =       [[-1, 0], [0, -1], [1, 0], [0, 1]]  # up, left, down, right





class 					__lowerCAmelCase :




				def __init__(							self						,				_snake_case						,				_snake_case						,				_snake_case						,				_snake_case						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    pos_x
									_lowerCAmelCase						=    pos_y
									_lowerCAmelCase						=    (pos_y, pos_x)
									_lowerCAmelCase						=    goal_x
									_lowerCAmelCase						=    goal_y
									_lowerCAmelCase						=    parent





class 					__lowerCAmelCase :




				def __init__(							self						,				_snake_case						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    Node(start[1]						,				start[0]						,				goal[1]						,				goal[0]						,				_snake_case		)
									_lowerCAmelCase						=    Node(goal[1]						,				goal[0]						,				goal[1]						,				goal[0]						,				_snake_case		)

									_lowerCAmelCase						=    [self.start]
									_lowerCAmelCase						=    False




				def 							snake_case   (							self		):



									"""simple docstring"""





									while self.node_queue:
														_lowerCAmelCase						=    self.node_queue.pop(0		)

														if current_node.pos == self.target.pos:
																			_lowerCAmelCase						=    True
																			return self.retrace_path(_snake_case		)

														_lowerCAmelCase						=    self.get_successors(_snake_case		)

														for node in successors:
																			self.node_queue.append(_snake_case		)

									if not self.reached:
														return [self.start.pos]
									return None




				def 							snake_case   (							self						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    []
									for action in delta:
														_lowerCAmelCase						=    parent.pos_x + action[1]
														_lowerCAmelCase						=    parent.pos_y + action[0]
														if not (0 <= pos_x <= len(grid[0]		) - 1 and 0 <= pos_y <= len(_snake_case		) - 1):
																			continue

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

														successors.append(
														    Node(_snake_case						,				_snake_case						,				self.target.pos_y						,				self.target.pos_x						,				_snake_case		)		)
									return successors




				def 							snake_case   (							self						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    node
									_lowerCAmelCase						=    []
									while current_node is not None:
														path.append((current_node.pos_y, current_node.pos_x)		)
														_lowerCAmelCase						=    current_node.parent
									path.reverse()
									return path





class 					__lowerCAmelCase :




				def __init__(							self						,				_snake_case						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    BreadthFirstSearch(_snake_case						,				_snake_case		)
									_lowerCAmelCase						=    BreadthFirstSearch(_snake_case						,				_snake_case		)
									_lowerCAmelCase						=    False




				def 							snake_case   (							self		):



									"""simple docstring"""





									while self.fwd_bfs.node_queue or self.bwd_bfs.node_queue:
														_lowerCAmelCase						=    self.fwd_bfs.node_queue.pop(0		)
														_lowerCAmelCase						=    self.bwd_bfs.node_queue.pop(0		)

														if current_bwd_node.pos == current_fwd_node.pos:
																			_lowerCAmelCase						=    True
																			return self.retrace_bidirectional_path(
																			    _snake_case						,				_snake_case		)

														_lowerCAmelCase						=    current_bwd_node
														_lowerCAmelCase						=    current_fwd_node

														_lowerCAmelCase						=    {
														    self.fwd_bfs: self.fwd_bfs.get_successors(_snake_case		),
														    self.bwd_bfs: self.bwd_bfs.get_successors(_snake_case		),
														}

														for bfs in [self.fwd_bfs, self.bwd_bfs]:
																			for node in successors[bfs]:
																								bfs.node_queue.append(_snake_case		)

									if not self.reached:
														return [self.fwd_bfs.start.pos]
									return None




				def 							snake_case   (							self						,				_snake_case						,				_snake_case		):



									"""simple docstring"""





									_lowerCAmelCase						=    self.fwd_bfs.retrace_path(_snake_case		)
									_lowerCAmelCase						=    self.bwd_bfs.retrace_path(_snake_case		)
									bwd_path.pop()
									bwd_path.reverse()
									_lowerCAmelCase						=    fwd_path + bwd_path
									return path


if __name__ == "__main__":
	# all coordinates are given in format [y,x]
	import doctest

	doctest.testmod()
	A__	      =       (0, 0)
	A__	      =       (len(grid) - 1, len(grid[0]) - 1)
	for elem in grid:
		print(elem)

	A__	      =       time.time()
	A__	      =       BreadthFirstSearch(init, goal)
	A__	      =       bfs.search()
	A__	      =       time.time() - start_bfs_time

	print("""Unidirectional BFS computation time : """, bfs_time)

	A__	      =       time.time()
	A__	      =       BidirectionalBreadthFirstSearch(init, goal)
	A__	      =       bd_bfs.search()
	A__	      =       time.time() - start_bd_bfs_time

	print("""Bidirectional BFS computation time : """, bd_bfs_time)










def   a_    ( lowerCAmelCase_      :			int	):

   if p < 2:
      raise ValueError('p should not be less than 2!'	)
   elif p == 2:
      return True

   __lowerCAmelCase								=	4
   __lowerCAmelCase								=	(1 << p) - 1
   for _ in range(p - 2	):
      __lowerCAmelCase								=	((s * s) - 2) % m
   return s == 0


if __name__ == "__main__":
     print(lucas_lehmer_test(7))
     print(lucas_lehmer_test(11))

