





"""simple docstring"""





from __future__ import annotations

from typing import Generic, TypeVar

SCREAMING_SNAKE_CASE__					=   TypeVar("T")

class 		lowercase					(					Generic[T]					):





      def __init__(       self      ,						lowercase )		->     None:
            lowerCAmelCase  						=       data
            lowerCAmelCase  						=       self
            lowerCAmelCase  						=       0







class 		lowercase					(					Generic[T]					):





      def __init__(       self )		->     None:
            # map from node name to the node object
            lowerCAmelCase  						=       {}





      def     _snake_case			(       self      ,						lowercase )		->     None:
            # create a new set with x as its member
            lowerCAmelCase  						=       DisjointSetTreeNode(lowercase )





      def     _snake_case			(       self      ,						lowercase )		->     DisjointSetTreeNode[T]:
            # find the set x belongs to (with path-compression)
            lowerCAmelCase  						=       self.map[data]
            if elem_ref != elem_ref.parent:
                  lowerCAmelCase  						=       self.find_set(elem_ref.parent.data )
            return elem_ref.parent





      def     _snake_case			(       self      ,						lowercase      ,						lowercase )		->     None:
            # helper function for union operation
            if nodea.rank > nodea.rank:
                  lowerCAmelCase  						=       nodea
            else:
                  lowerCAmelCase  						=       nodea
                  if nodea.rank == nodea.rank:
                        nodea.rank += 1





      def     _snake_case			(       self      ,						lowercase      ,						lowercase )		->     None:
            # merge 2 disjoint sets
            self.link(self.find_set(lowercase )      ,						self.find_set(lowercase ) )







class 		lowercase					(					Generic[T]					):





      def __init__(       self )		->     None:
            # connections: map from the node to the neighbouring nodes (with weights)
            lowerCAmelCase  						=       {}





      def     _snake_case			(       self      ,						lowercase )		->     None:
            # add a node ONLY if its not present in the graph
            if node not in self.connections:
                  lowerCAmelCase  						=       {}





      def     _snake_case			(       self      ,						lowercase      ,						lowercase      ,						lowercase )		->     None:
            # add an edge with the given weight
            self.add_node(lowercase )
            self.add_node(lowercase )
            lowerCAmelCase  						=       weight
            lowerCAmelCase  						=       weight





      def     _snake_case			(       self )		->     GraphUndirectedWeighted[T]:
            lowerCAmelCase  						=       []
            lowerCAmelCase  						=       set()
            for start in self.connections:
                  for end in self.connections[start]:
                        if (start, end) not in seen:
                              seen.add((end, start) )
                              edges.append((start, end, self.connections[start][end]) )
            edges.sort(key=lambda lowercase : x[2] )

            # creating the disjoint set
            lowerCAmelCase  						=       DisjointSetTree[T]()
            for node in self.connections:
                  disjoint_set.make_set(lowercase )

            # MST generation
            lowerCAmelCase  						=       0
            lowerCAmelCase  						=       0
            lowerCAmelCase  						=       GraphUndirectedWeighted[T]()
            while num_edges < len(self.connections ) - 1:
                  lowerCAmelCase						,		lowerCAmelCase						,		lowerCAmelCase  						=       edges[index]
                  index += 1
                  lowerCAmelCase  						=       disjoint_set.find_set(lowercase )
                  lowerCAmelCase  						=       disjoint_set.find_set(lowercase )
                  if parent_u != parent_v:
                        num_edges += 1
                        graph.add_edge(lowercase      ,						lowercase      ,						lowercase )
                        disjoint_set.union(lowercase      ,						lowercase )
            return graph













"""simple docstring"""





SCREAMING_SNAKE_CASE__					=   {
    "A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".", "F": "..-.", "G": "--.",
    "H": "....", "I": "..", "J": ".---", "K": "-.-", "L": ".-..", "M": "--", "N": "-.",
    "O": "---", "P": ".--.", "Q": "--.-", "R": ".-.", "S": "...", "T": "-", "U": "..-",
    "V": "...-", "W": ".--", "X": "-..-", "Y": "-.--", "Z": "--..", "1": ".----",
    "2": "..---", "3": "...--", "4": "....-", "5": ".....", "6": "-....", "7": "--...",
    "8": "---..", "9": "----.", "0": "-----", "&": ".-...", "@": ".--.-.",
    ":": "---...", ",": "--..--", ".": ".-.-.-", "'": ".----.", "\"": ".-..-.",
    "?": "..--..", "/": "-..-.", "=": "-...-", "+": ".-.-.", "-": "-....-",
    "(": "-.--.", ")": "-.--.-", "!": "-.-.--", " ": "/"
}  # Exclamation mark is not in ITU-R recommendation
# fmt: on
SCREAMING_SNAKE_CASE__					=   {value: key for key, value in MORSE_CODE_DICT.items()}


def 			UpperCAmelCase__							(  SCREAMING_SNAKE_CASE     :						str			):







      '''simple docstring'''




      return " ".join(MORSE_CODE_DICT[char] for char in message.upper()			)


def 			UpperCAmelCase__							(  SCREAMING_SNAKE_CASE     :						str			):







      '''simple docstring'''




      return "".join(REVERSE_DICT[char] for char in message.split()			)


def 			UpperCAmelCase__							(  ):







      '''simple docstring'''




      lowerCAmelCase  						=       """Morse code here!"""
      print(SCREAMING_SNAKE_CASE			)
      lowerCAmelCase  						=       encrypt(SCREAMING_SNAKE_CASE			)
      print(SCREAMING_SNAKE_CASE			)
      lowerCAmelCase  						=       decrypt(SCREAMING_SNAKE_CASE			)
      print(SCREAMING_SNAKE_CASE			)


if __name__ == "__main__":
       main()






