
"""simple docstring"""




from __future__ import annotations

import time

a		:       Tuple     						=       list[tuple[int, int]]

a		:       List[str]     						=       [
    [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		:       Dict     						=       [[-1, 0], [0, -1], [1, 0], [0, 1]]  # up, left, down, right







class     lowercase:



     def __init__(							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     Optional[int]:







         """simple docstring"""



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







class     lowercase:



     def __init__(							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     Optional[int]:







         """simple docstring"""



         a__		=			Node(start[1]     ,				start[0]     ,				goal[1]     ,				goal[0]     ,				__SCREAMING_SNAKE_CASE   )
         a__		=			Node(goal[1]     ,				goal[0]     ,				goal[1]     ,				goal[0]     ,				__SCREAMING_SNAKE_CASE   )

         a__		=			[self.start]
         a__		=			False



     def 			lowercase__  (							self   )		->     Path | None:







         """simple docstring"""



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

             if current_node.pos == self.target.pos:
                 a__		=			True
                 return self.retrace_path(__SCREAMING_SNAKE_CASE   )

             a__		=			self.get_successors(__SCREAMING_SNAKE_CASE   )

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

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



     def 			lowercase__  (							self     ,				__SCREAMING_SNAKE_CASE   )		->     list[Node]:







         """simple docstring"""



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

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

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




     def 			lowercase__  (							self     ,				__SCREAMING_SNAKE_CASE   )		->     Path:







         """simple docstring"""



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







class     lowercase:



     def __init__(							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     str:







         """simple docstring"""



         a__		=			BreadthFirstSearch(__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )
         a__		=			BreadthFirstSearch(__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )
         a__		=			False



     def 			lowercase__  (							self   )		->     Path | None:







         """simple docstring"""



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

             if current_bwd_node.pos == current_fwd_node.pos:
                 a__		=			True
                 return self.retrace_bidirectional_path(
                     __SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )

             a__		=			current_bwd_node
             a__		=			current_fwd_node

             a__		=			{
                 self.fwd_bfs: self.fwd_bfs.get_successors(__SCREAMING_SNAKE_CASE   ),
                 self.bwd_bfs: self.bwd_bfs.get_successors(__SCREAMING_SNAKE_CASE   ),
             }

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

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




     def 			lowercase__  (							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     Path:







         """simple docstring"""



         a__		=			self.fwd_bfs.retrace_path(__SCREAMING_SNAKE_CASE   )
         a__		=			self.bwd_bfs.retrace_path(__SCREAMING_SNAKE_CASE   )
         bwd_path.pop()
         bwd_path.reverse()
         a__		=			fwd_path + bwd_path
         return path


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

    doctest.testmod()
    a		:       List[Any]     						=       (0, 0)
    a		:       Tuple     						=       (len(grid) - 1, len(grid[0]) - 1)
    for elem in grid:
        print(elem)

    a		:       Dict     						=       time.time()
    a		:       Optional[int]     						=       BreadthFirstSearch(init, goal)
    a		:       Dict     						=       bfs.search()
    a		:       List[str]     						=       time.time() - start_bfs_time

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

    a		:       Tuple     						=       time.time()
    a		:       int     						=       BidirectionalBreadthFirstSearch(init, goal)
    a		:       str     						=       bd_bfs.search()
    a		:       List[Any]     						=       time.time() - start_bd_bfs_time

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




"""simple docstring"""




import math







class     lowercase:



     def 			lowercase__  (							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     int:







         """simple docstring"""



         a__		=			0.0
         a__		=			0.0
         for i in range(len(__SCREAMING_SNAKE_CASE   )   ):
             da += math.pow((sample[i] - weights[0][i])     ,				2   )
             da += math.pow((sample[i] - weights[1][i])     ,				2   )
             return 0 if da > da else 1
         return 0




     def 			lowercase__  (							self     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE     ,				__SCREAMING_SNAKE_CASE   )		->     list[list[int | float]]:







         """simple docstring"""



         for i in range(len(__SCREAMING_SNAKE_CASE   )   ):
             weights[j][i] += alpha * (sample[i] - weights[j][i])
         return weights




def     __magic_name__		(					)     ->						None:
    # Training Examples ( m, n )
    a__		=			[[1, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0], [0, 0, 1, 1]]

    # weight initialization ( n, C )
    a__		=			[[0.2, 0.6, 0.5, 0.9], [0.8, 0.4, 0.7, 0.3]]

    # training
    a__		=			SelfOrganizingMap()
    a__		=			3
    a__		=			0.5

    for _ in range(UpperCamelCase     ):
        for j in range(len(UpperCamelCase     )     ):
            # training sample
            a__		=			training_samples[j]

            # Compute the winning vector
            a__		=			self_organizing_map.get_winner(UpperCamelCase							,		UpperCamelCase     )

            # Update the winning vector
            a__		=			self_organizing_map.update(UpperCamelCase							,		UpperCamelCase							,		UpperCamelCase							,		UpperCamelCase     )

    # classify test sample
    a__		=			[0, 0, 0, 1]
    a__		=			self_organizing_map.get_winner(UpperCamelCase							,		UpperCamelCase     )

    # results
    print(f'Clusters that the test sample belongs to : {winner}'     )
    print(f'Weights that have been trained : {weights}'     )


# running the main() function
if __name__ == "__main__":
    main()


