import numpy as np





class   lowerCAmelCase    :



     def __init__(       self					,   lowerCAmelCase__=5					,   lowerCAmelCase__=5							):
            _A=						depth
            _A=						0
            _A=						None
            _A=						None
            _A=						min_leaf_size
            _A=						None



     def       a__	(       self					,   lowerCAmelCase__					,   lowerCAmelCase__							):
            if labels.ndim != 1:
                   print('Error: Input labels must be one dimensional'							)

            return np.mean((labels - prediction) ** 2							)



     def       a__	(       self					,   lowerCAmelCase__					,   lowerCAmelCase__							):
            if x.ndim != 1:
                   print('Error: Input data set must be one dimensional'							)
                   return
            if len(_SCREAMING_SNAKE_CASE							) != len(_SCREAMING_SNAKE_CASE							):
                   print('Error: X and y have different lengths'							)
                   return
            if y.ndim != 1:
                   print('Error: Data set labels must be one dimensional'							)
                   return

            if len(_SCREAMING_SNAKE_CASE							) < 2 * self.min_leaf_size:
                   _A=						np.mean(_SCREAMING_SNAKE_CASE							)
                   return

            if self.depth == 1:
                   _A=						np.mean(_SCREAMING_SNAKE_CASE							)
                   return

            _A=						0
            _A=						self.mean_squared_error(_SCREAMING_SNAKE_CASE					,   np.mean(_SCREAMING_SNAKE_CASE							)							) * 2
            for i in range(len(_SCREAMING_SNAKE_CASE							)							):
                   if len(x[:i]							) < self.min_leaf_size:
                          continue
                   elif len(x[i:]							) < self.min_leaf_size:
                          continue
                   else:
                          _A=						self.mean_squared_error(x[:i]					,   np.mean(y[:i]							)							)
                          _A=						self.mean_squared_error(x[i:]					,   np.mean(y[i:]							)							)
                          _A=						error_left + error_right
                          if error < min_error:
                                 _A=						i
                                 _A=						error

            if best_split != 0:
                   _A=						x[:best_split]
                   _A=						y[:best_split]
                   _A=						x[best_split:]
                   _A=						y[best_split:]

                   _A=						x[best_split]
                   _A=						DecisionTree(
                       depth=self.depth - 1					,   min_leaf_size=self.min_leaf_size							)
                   _A=						DecisionTree(
                       depth=self.depth - 1					,   min_leaf_size=self.min_leaf_size							)
                   self.left.train(_SCREAMING_SNAKE_CASE					,   _SCREAMING_SNAKE_CASE							)
                   self.right.train(_SCREAMING_SNAKE_CASE					,   _SCREAMING_SNAKE_CASE							)
            else:
                   _A=						np.mean(_SCREAMING_SNAKE_CASE							)

            return





     def       a__	(       self					,   lowerCAmelCase__							):
            if self.prediction is not None:
                   return self.prediction
            elif self.left or self.right is not None:
                   if x >= self.decision_boundary:
                          return self.right.predict(_SCREAMING_SNAKE_CASE							)
                   else:
                          return self.left.predict(_SCREAMING_SNAKE_CASE							)
            else:
                   print('Error: Decision tree not yet trained'							)
                   return None





class   lowerCAmelCase    :



     @staticmethod
     def       a__	(       lowerCAmelCase__					,   lowerCAmelCase__							):
            _A=						float(0							)
            for label in labels:
                   squared_error_sum += (label - prediction) ** 2

            return float(squared_error_sum / labels.size							)


def 				UpperCamelCase					(     )		->    Optional[Any]:




       '''simple docstring'''






       _A=						np.arange(-1.0							,       1.0							,       0.005 )
       _A=						np.sin(lowerCAmelCase_ )

       _A=						DecisionTree(depth=10							,       min_leaf_size=10 )
       tree.train(lowerCAmelCase_							,       lowerCAmelCase_ )

       _A=						(np.random.rand(10 ) * 2) - 1
       _A=						np.array([tree.predict(lowerCAmelCase_ ) for x in test_cases] )
       _A=						np.mean((predictions - test_cases) ** 2 )

       print('Test values: ' + str(lowerCAmelCase_ ) )
       print('Predictions: ' + str(lowerCAmelCase_ ) )
       print('Average error: ' + str(lowerCAmelCase_ ) )


if __name__ == "__main__":
      main()
      import doctest

      doctest.testmod(name='''mean_squarred_error''', verbose=True)



def 			__SCREAMING_SNAKE_CASE		(		UpperCamelCase		:      int     ,					UpperCamelCase		:      list[tuple[int, int, int]]	)     ->	list[tuple[int, int, int]]:



	"""simple docstring"""






	a_     			=   sorted(UpperCamelCase     ,					key=lambda UpperCamelCase	: edge[2]	)

	a_     			=   list(range(UpperCamelCase	)	)

	def find_parent(UpperCamelCase		:      Any	):
		if i != parent[i]:
			a_     			=   find_parent(parent[i]	)
		return parent[i]

	a_     			=   0
	a_     			=   []

	for edge in edges:
		a_     			=   find_parent(edge[0]	)
		a_     			=   find_parent(edge[1]	)
		if parent_a != parent_b:
			minimum_spanning_tree_cost += edge[2]
			minimum_spanning_tree.append(UpperCamelCase	)
			a_     			=   parent_b

	return minimum_spanning_tree


if __name__ == "__main__":  # pragma: no cover
			_A     ,				_A							     =       list(map(int, input().strip().split()))
			_A							     =       []

			for _ in range(num_edges):
						_A     ,				_A     ,				_A							     =       (int(x) for x in input().strip().split())
						edges.append((nodea, nodea, cost))

			kruskal(num_nodes, edges)