






from __future__ import annotations

from scipy.special import comb  # type: ignore
class     a    :



      """simple docstring"""


      def __init__(      self					:			Dict		,      __lowercase					:			list[tuple[float, float]]					)							->      List[str]:
        __UpperCAmelCase							:	Union[str, Any]           =  list_of_points
        # Degree determines the flexibility of the curve.
        # Degree = 1 will produce a straight line.
        __UpperCAmelCase							:	str           =  len(__lowercase					) - 1
      def 	UpperCAmelCase      (      self					:			List[str]		,      __lowercase					:			float					)							->      list[float]:
        assert 0 <= t <= 1, "Time t must be between 0 and 1."
        __UpperCAmelCase							:	list[float]           =  []
        for i in range(len(self.list_of_points					)					):
          # basis function for each i
          output_values.append(
              comb(self.degree		,      __lowercase					) * ((1 - t) ** (self.degree - i)) * (t**i)					)
        # the basis must sum up to 1 for it to produce a valid Bezier curve.
        assert round(sum(__lowercase					)		,      5					) == 1
        return output_values
      def 	UpperCAmelCase      (      self					:			List[str]		,      __lowercase					:			float					)							->      tuple[float, float]:
        assert 0 <= t <= 1, "Time t must be between 0 and 1."

        __UpperCAmelCase							:	Optional[int]           =  self.basis_function(__lowercase					)
        __UpperCAmelCase							:	Optional[Any]           =  0.0
        __UpperCAmelCase							:	str           =  0.0
        for i in range(len(self.list_of_points					)					):
          # For all points, sum up the product of i-th basis function and i-th point.
          x += basis_function[i] * self.list_of_points[i][0]
          y += basis_function[i] * self.list_of_points[i][1]
        return (x, y)




      def 	UpperCAmelCase      (      self					:			Union[str, Any]		,      __lowercase					:			float = 0.01					)							->      Tuple:
        from matplotlib import pyplot as plt  # type: ignore

        __UpperCAmelCase							:	list[float]           =  []  # x coordinates of points to plot
        __UpperCAmelCase							:	list[float]           =  []  # y coordinates of points to plot

        __UpperCAmelCase							:	str           =  0.0
        while t <= 1:
          __UpperCAmelCase							:	int           =  self.bezier_curve_function(__lowercase					)
          to_plot_x.append(value[0]					)
          to_plot_y.append(value[1]					)
          t += step_size

        __UpperCAmelCase							:	Any           =  [i[0] for i in self.list_of_points]
        __UpperCAmelCase							:	List[str]           =  [i[1] for i in self.list_of_points]

        plt.plot(
            __lowercase		,      __lowercase		,      color="""blue"""		,      label="""Curve of Degree """ + str(self.degree					)		,      )
        plt.scatter(__lowercase		,      __lowercase		,      color="""red"""		,      label="""Control Points"""					)
        plt.legend()
        plt.show()


if __name__ == "__main__":
       import doctest

       doctest.testmod()

       BezierCurve([(1, 2), (3, 5)]).plot_curve()  # degree 1
       BezierCurve([(0, 0), (5, 5), (5, 0)]).plot_curve()  # degree 2
       BezierCurve([(0, 0), (5, 5), (5, 0), (2.5, -2.5)]).plot_curve()  # degree 3










from functools import lru_cache






@lru_cache
def 				lowerCamelCase__      (    __lowerCamelCase			:     int		):
  if num < 0:
    raise ValueError("""Number should not be negative."""		)

  return 1 if num in (0, 1) else num * factorial(num - 1		)


if __name__ == "__main__":
       import doctest

       doctest.testmod()


