
from __future__ import annotations

import math
import random
from collections.abc import Collection
from typing import overload






class UpperCAmelCase   :





   '''simple docstring'''


   def __init__(					self     :							Tuple			,			lowerCAmelCase_     :							Collection[float] | None = None     ):

      """simple docstring"""
      if components is None:
         _A:  str					=       []
      _A:  int					=       list(lowerCAmelCase_     )


   def __len__(					self     :							List[str]     ):

      """simple docstring"""
      return len(self.__components     )


   def __str__(					self     :							int     ):

      """simple docstring"""
      return "(" + ",".join(map(lowerCAmelCase_			,			self.__components     )     ) + ")"


   def __add__(					self     :							int			,			lowerCAmelCase_     :							Vector     ):

      """simple docstring"""
      _A:  List[Any]					=       len(self     )
      if size == len(lowerCAmelCase_     ):
         _A:  Dict					=       [self.__components[i] + other.component(lowerCAmelCase_     ) for i in range(lowerCAmelCase_     )]
         return Vector(lowerCAmelCase_     )
      else:
         raise Exception('''must have the same size'''     )


   def __sub__(					self     :							Dict			,			lowerCAmelCase_     :							Vector     ):

      """simple docstring"""
      _A:  List[str]					=       len(self     )
      if size == len(lowerCAmelCase_     ):
         _A:  Dict					=       [self.__components[i] - other.component(lowerCAmelCase_     ) for i in range(lowerCAmelCase_     )]
         return Vector(lowerCAmelCase_     )
      else:  # error case
         raise Exception('''must have the same size'''     )


   @overload
   def __mul__(					self     :							Union[str, Any]			,			lowerCAmelCase_     :							float     ):

      """simple docstring"""
      ...


   @overload
   def __mul__(					self     :							List[Any]			,			lowerCAmelCase_     :							Vector     ):

      """simple docstring"""
      ...


   def __mul__(					self     :							List[Any]			,			lowerCAmelCase_     :							float | Vector     ):

      """simple docstring"""
      if isinstance(lowerCAmelCase_			,			(float, int)     ):
         _A:  Tuple					=       [c * other for c in self.__components]
         return Vector(lowerCAmelCase_     )
      elif isinstance(lowerCAmelCase_			,			lowerCAmelCase_     ) and len(self     ) == len(lowerCAmelCase_     ):
         _A:  str					=       len(self     )
         _A:  int					=       [self.__components[i] * other.component(lowerCAmelCase_     ) for i in range(lowerCAmelCase_     )]
         return sum(lowerCAmelCase_     )
      else:  # error case
         raise Exception('''invalid operand!'''     )


   def  __magic_name__				(					self     :							Dict     ):

      """simple docstring"""
      return Vector(self.__components     )


   def  __magic_name__				(					self     :							Tuple			,			lowerCAmelCase_     :							int     ):

      """simple docstring"""
      if isinstance(lowerCAmelCase_			,			lowerCAmelCase_     ) and -len(self.__components     ) <= i < len(self.__components     ):
         return self.__components[i]
      else:
         raise Exception('''index out of range'''     )


   def  __magic_name__				(					self     :							Tuple			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							float     ):

      """simple docstring"""
      assert -len(self.__components     ) <= pos < len(self.__components     )
      _A:  Dict					=       value


   def  __magic_name__				(					self     :							Union[str, Any]     ):

      """simple docstring"""
      if len(self.__components     ) == 0:
         raise Exception('''Vector is empty'''     )
      _A:  Optional[Any]					=       [c**2 for c in self.__components]
      return math.sqrt(sum(lowerCAmelCase_     )     )


   def  __magic_name__				(					self     :							Optional[int]			,			lowerCAmelCase_     :							Vector			,			lowerCAmelCase_     :							bool = False     ):

      """simple docstring"""
      _A:  List[Any]					=       self * other
      _A:  str					=       self.euclidean_length() * other.euclidean_length()
      if deg:
         return math.degrees(math.acos(num / den     )     )
      else:
         return math.acos(num / den     )






def   lowerCamelCase__							(					a      )      ->   Vector:
   assert isinstance(a		,		a      )
   return Vector([0] * dimension      )






def   lowerCamelCase__							(					a		,		a      )      ->   Vector:
   assert isinstance(a		,		a      ) and (isinstance(a		,		a      ))
   _A:  Optional[int]					=       [0] * dimension
   _A:  Optional[Any]					=       1
   return Vector(a      )






def   lowerCamelCase__							(					a		,		a		,		a      )      ->   Vector:
   assert (
       isinstance(a		,		a      )
       and isinstance(a		,		a      )
       and (isinstance(a		,		(int, float)      ))
   )
   return x * scalar + y






def   lowerCamelCase__							(					a		,		a		,		a      )      ->   Vector:
   random.seed(a      )
   _A:  Optional[int]					=       [random.randint(a		,		a      ) for _ in range(a      )]
   return Vector(a      )






class UpperCAmelCase   :





   '''simple docstring'''


   def __init__(					self     :							Optional[Any]			,			lowerCAmelCase_     :							list[list[float]]			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							int     ):

      """simple docstring"""
      _A:  List[Any]					=       matrix
      _A:  List[Any]					=       w
      _A:  int					=       h


   def __str__(					self     :							Tuple     ):

      """simple docstring"""
      _A:  Tuple					=       ''''''
      for i in range(self.__height     ):
         ans += "|"
         for j in range(self.__width     ):
            if j < self.__width - 1:
               ans += str(self.__matrix[i][j]     ) + ","
            else:
               ans += str(self.__matrix[i][j]     ) + "|\n"
      return ans


   def __add__(					self     :							Optional[int]			,			lowerCAmelCase_     :							Matrix     ):

      """simple docstring"""
      if self.__width == other.width() and self.__height == other.height():
         _A:  Optional[Any]					=       []
         for i in range(self.__height     ):
            _A:  str					=       [
                self.__matrix[i][j] + other.component(lowerCAmelCase_			,			lowerCAmelCase_     )
                for j in range(self.__width     )
            ]
            matrix.append(lowerCAmelCase_     )
         return Matrix(lowerCAmelCase_			,			self.__width			,			self.__height     )
      else:
         raise Exception('''matrix must have the same dimension!'''     )


   def __sub__(					self     :							int			,			lowerCAmelCase_     :							Matrix     ):

      """simple docstring"""
      if self.__width == other.width() and self.__height == other.height():
         _A:  Tuple					=       []
         for i in range(self.__height     ):
            _A:  Any					=       [
                self.__matrix[i][j] - other.component(lowerCAmelCase_			,			lowerCAmelCase_     )
                for j in range(self.__width     )
            ]
            matrix.append(lowerCAmelCase_     )
         return Matrix(lowerCAmelCase_			,			self.__width			,			self.__height     )
      else:
         raise Exception('''matrices must have the same dimension!'''     )


   @overload
   def __mul__(					self     :							int			,			lowerCAmelCase_     :							float     ):

      """simple docstring"""
      ...


   @overload
   def __mul__(					self     :							Dict			,			lowerCAmelCase_     :							Vector     ):

      """simple docstring"""
      ...


   def __mul__(					self     :							List[Any]			,			lowerCAmelCase_     :							float | Vector     ):

      """simple docstring"""
      if isinstance(lowerCAmelCase_			,			lowerCAmelCase_     ):  # matrix-vector
         if len(lowerCAmelCase_     ) == self.__width:
            _A:  Optional[Any]					=       zero_vector(self.__height     )
            for i in range(self.__height     ):
               _A:  List[Any]					=       [
                   self.__matrix[i][j] * other.component(lowerCAmelCase_     )
                   for j in range(self.__width     )
               ]
               ans.change_component(lowerCAmelCase_			,			sum(lowerCAmelCase_     )     )
            return ans
         else:
            raise Exception(
                '''vector must have the same size as the '''
                '''number of columns of the matrix!'''     )
      elif isinstance(lowerCAmelCase_			,			(int, float)     ):  # matrix-scalar
         _A:  str					=       [
             [self.__matrix[i][j] * other for j in range(self.__width     )]
             for i in range(self.__height     )
         ]
         return Matrix(lowerCAmelCase_			,			self.__width			,			self.__height     )
      return None


   def  __magic_name__				(					self     :							List[str]     ):

      """simple docstring"""
      return self.__height


   def  __magic_name__				(					self     :							List[str]     ):

      """simple docstring"""
      return self.__width


   def  __magic_name__				(					self     :							Tuple			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							int     ):

      """simple docstring"""
      if 0 <= x < self.__height and 0 <= y < self.__width:
         return self.__matrix[x][y]
      else:
         raise Exception('''change_component: indices out of bounds'''     )


   def  __magic_name__				(					self     :							Optional[Any]			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							float     ):

      """simple docstring"""
      if 0 <= x < self.__height and 0 <= y < self.__width:
         _A:  List[str]					=       value
      else:
         raise Exception('''change_component: indices out of bounds'''     )


   def  __magic_name__				(					self     :							Optional[int]			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							int     ):

      """simple docstring"""
      if self.__height != self.__width:
         raise Exception('''Matrix is not square'''     )
      _A:  Optional[Any]					=       self.__matrix[:x] + self.__matrix[x + 1 :]
      for i in range(len(lowerCAmelCase_     )     ):
         _A:  Optional[Any]					=       minor[i][:y] + minor[i][y + 1 :]
      return Matrix(lowerCAmelCase_			,			self.__width - 1			,			self.__height - 1     ).determinant()


   def  __magic_name__				(					self     :							List[Any]			,			lowerCAmelCase_     :							int			,			lowerCAmelCase_     :							int     ):

      """simple docstring"""
      if self.__height != self.__width:
         raise Exception('''Matrix is not square'''     )
      if 0 <= x < self.__height and 0 <= y < self.__width:
         return (-1) ** (x + y) * self.minor(lowerCAmelCase_			,			lowerCAmelCase_     )
      else:
         raise Exception('''Indices out of bounds'''     )


   def  __magic_name__				(					self     :							Tuple     ):

      """simple docstring"""
      if self.__height != self.__width:
         raise Exception('''Matrix is not square'''     )
      if self.__height < 1:
         raise Exception('''Matrix has no element'''     )
      elif self.__height == 1:
         return self.__matrix[0][0]
      elif self.__height == 2:
         return (
             self.__matrix[0][0] * self.__matrix[1][1]
             - self.__matrix[0][1] * self.__matrix[1][0]
         )
      else:
         _A:  Optional[Any]					=       [
             self.__matrix[0][y] * self.cofactor(0			,			lowerCAmelCase_     ) for y in range(self.__width     )
         ]
         return sum(lowerCAmelCase_     )






def   lowerCamelCase__							(					a      )      ->   Matrix:
   _A:  list[list[float]]					=       [[0] * n for _ in range(a      )]
   return Matrix(a		,		a		,		a      )






def   lowerCamelCase__							(					a		,		a		,		a		,		a      )      ->   Matrix:
   random.seed(a      )
   _A:  list[list[float]]					=       [
       [random.randint(a		,		a      ) for _ in range(a      )] for _ in range(a      )
   ]
   return Matrix(a		,		a		,		a      )





UpperCAmelCase__		:     Optional[Any]     			=      {
    'A': ['B', 'C', 'E'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F', 'G'],
    'D': ['B'],
    'E': ['A', 'B', 'D'],
    'F': ['C'],
    'G': ['C'],
}






def   lowerCamelCase__							(					a		,		a		,		a      )      ->   list[str]:
   _A:  Union[str, Any]					=       set()
   # keep track of all the paths to be checked
   _A:  Union[str, Any]					=       [[start]]

   # return path if start is goal
   if start == goal:
      return [start]

   # keeps looping until all possible paths have been checked
   while queue:
      # pop the first path from the queue
      _A:  Any					=       queue.pop(0      )
      # get the last node from the path
      _A:  Union[str, Any]					=       path[-1]
      if node not in explored:
         _A:  str					=       graph[node]
         # go through all neighbour nodes, construct a new path and
         # push it into the queue
         for neighbour in neighbours:
            _A:  Optional[int]					=       list(a      )
            new_path.append(a      )
            queue.append(a      )
            # return path if neighbour is goal
            if neighbour == goal:
               return new_path

            # mark node as explored
         explored.add(a      )

    # in case there's no path between the 2 nodes
   return []






def   lowerCamelCase__							(					a		,		a		,		a      )      ->   int:
   if not graph or start not in graph or target not in graph:
      return -1
   if start == target:
      return 0
   _A:  Any					=       [start]
   _A:  List[str]					=       set(a      )
   # Keep tab on distances from `start` node.
   _A:  Optional[int]					=       {start: 0, target: -1}
   while queue:
      _A:  Union[str, Any]					=       queue.pop(0      )
      if node == target:
         _A:  Dict					=       (
             dist[node] if dist[target] == -1 else min(dist[target]		,		dist[node]      )
         )
      for adjacent in graph[node]:
         if adjacent not in visited:
            visited.add(a      )
            queue.append(a      )
            _A:  List[Any]					=       dist[node] + 1
   return dist[target]


if __name__ == "__main__":
   print(bfs_shortest_path(demo_graph, 'G', 'D'))  # returns ['G', 'C', 'A', 'B', 'D']
   print(bfs_shortest_path_distance(demo_graph, 'G', 'D'))  # returns 4



