'''simple docstring'''




from __future__ import annotations

from collections.abc import Iterator
from typing import Any




class     a__      :






     def __init__( self		:		List[Any]  ,				a		:		Any    ):





         """simple docstring"""



         __lowerCamelCase		=  data
         __lowerCamelCase		=  None




class     a__      :






     def __init__( self		:		Any    ):





         """simple docstring"""



         __lowerCamelCase		=  None
         __lowerCamelCase		=  None






     def __iter__( self		:		Any    ):





         """simple docstring"""



         __lowerCamelCase		=  self.head
         while self.head:
             yield node.data
             __lowerCamelCase		=  node.next
             if node == self.head:
                 break






     def __len__( self		:		Any    ):





         """simple docstring"""



         return sum(1 for _ in self    )






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





         """simple docstring"""



         return "->".join(str(a    ) for item in iter(self    )    )






     def    SCREAMING_SNAKE_CASE__   ( self		:		str  ,				a		:		Any    ):





         """simple docstring"""



         self.insert_nth(len(self    )  ,				a    )






     def    SCREAMING_SNAKE_CASE__   ( self		:		Optional[Any]  ,				a		:		Any    ):





         """simple docstring"""



         self.insert_nth(0  ,				a    )






     def    SCREAMING_SNAKE_CASE__   ( self		:		int  ,				a		:		int  ,				a		:		Any    ):





         """simple docstring"""



         if index < 0 or index > len(self    ):
             raise IndexError('''list index out of range.'''    )
         __lowerCamelCase		=  Node(a    )
         if self.head is None:
             __lowerCamelCase		=  new_node  # first node points itself
             __lowerCamelCase		=  __lowerCamelCase		=  new_node
         elif index == 0:  # insert at head
             __lowerCamelCase		=  self.head
             __lowerCamelCase		=  __lowerCamelCase		=  new_node
         else:
             __lowerCamelCase		=  self.head
             for _ in range(index - 1    ):
                 __lowerCamelCase		=  temp.next
             __lowerCamelCase		=  temp.next
             __lowerCamelCase		=  new_node
             if index == len(self    ) - 1:  # insert at tail
                 __lowerCamelCase		=  new_node






     def    SCREAMING_SNAKE_CASE__   ( self		:		Dict    ):





         """simple docstring"""



         return self.delete_nth(0    )






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





         """simple docstring"""



         return self.delete_nth(len(self    ) - 1    )






     def    SCREAMING_SNAKE_CASE__   ( self		:		List[Any]  ,				a		:		int = 0    ):





         """simple docstring"""



         if not 0 <= index < len(self    ):
             raise IndexError('''list index out of range.'''    )
         __lowerCamelCase		=  self.head
         if self.head == self.tail:  # just one node
             __lowerCamelCase		=  __lowerCamelCase		=  None
         elif index == 0:  # delete head node
             __lowerCamelCase		=  self.tail.next.next
             __lowerCamelCase		=  self.head.next
         else:
             __lowerCamelCase		=  self.head
             for _ in range(index - 1    ):
                 __lowerCamelCase		=  temp.next
             __lowerCamelCase		=  temp.next
             __lowerCamelCase		=  temp.next.next
             if index == len(self    ) - 1:  # delete at tail
                 __lowerCamelCase		=  temp
         return delete_node.data






     def    SCREAMING_SNAKE_CASE__   ( self		:		Dict    ):





         """simple docstring"""



         return len(self    ) == 0






def __lowerCAmelCase (							)	->    None:
    __lowerCamelCase		=  CircularLinkedList()
    assert len(UpperCamelCase__				) == 0
    assert circular_linked_list.is_empty() is True
    assert str(UpperCamelCase__				) == ""

    try:
        circular_linked_list.delete_front()
        raise AssertionError  # This should not happen
    except IndexError:
        assert True  # This should happen

    try:
        circular_linked_list.delete_tail()
        raise AssertionError  # This should not happen
    except IndexError:
        assert True  # This should happen

    try:
        circular_linked_list.delete_nth(-1				)
        raise AssertionError
    except IndexError:
        assert True

    try:
        circular_linked_list.delete_nth(0				)
        raise AssertionError
    except IndexError:
        assert True

    assert circular_linked_list.is_empty() is True
    for i in range(5				):
        assert len(UpperCamelCase__				) == i
        circular_linked_list.insert_nth(UpperCamelCase__				,  i + 1				)
    assert str(UpperCamelCase__				) == "->".join(str(UpperCamelCase__				) for i in range(1				,  6				)				)

    circular_linked_list.insert_tail(6				)
    assert str(UpperCamelCase__				) == "->".join(str(UpperCamelCase__				) for i in range(1				,  7				)				)
    circular_linked_list.insert_head(0				)
    assert str(UpperCamelCase__				) == "->".join(str(UpperCamelCase__				) for i in range(0				,  7				)				)

    assert circular_linked_list.delete_front() == 0
    assert circular_linked_list.delete_tail() == 6
    assert str(UpperCamelCase__				) == "->".join(str(UpperCamelCase__				) for i in range(1				,  6				)				)
    assert circular_linked_list.delete_nth(2				) == 3

    circular_linked_list.insert_nth(2				,  3				)
    assert str(UpperCamelCase__				) == "->".join(str(UpperCamelCase__				) for i in range(1				,  6				)				)

    assert circular_linked_list.is_empty() is False


if __name__ == "__main__":
  import doctest

  doctest.testmod()






from __future__ import annotations

from scipy.special import comb  # type: ignore




class     snake_case__							:
				"""simple docstring"""



				def __init__(      self				:     Any					,      __lowerCamelCase				:     list[tuple[float, float]]							)					->     Tuple:
							a    =			list_of_points
							# Degree determines the flexibility of the curve.
							# Degree = 1 will produce a straight line.
							a    =			len(__lowerCamelCase							) - 1





				def 							__UpperCAmelCase							(      self				:     Union[str, Any]					,      __lowerCamelCase				:     float							)					->     list[float]:
							assert 0 <= t <= 1, "Time t must be between 0 and 1."
							a    =			[]
							for i in range(len(self.list_of_points							)							):
										# basis function for each i
										output_values.append(
										    comb(self.degree					,      __lowerCamelCase							) * ((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(__lowerCamelCase							)					,      5							) == 1
							return output_values





				def 							__UpperCAmelCase							(      self				:     Optional[Any]					,      __lowerCamelCase				:     float							)					->     tuple[float, float]:
							assert 0 <= t <= 1, "Time t must be between 0 and 1."

							a    =			self.basis_function(__lowerCamelCase							)
							a    =			0.0
							a    =			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				:     Optional[Any]					,      __lowerCamelCase				:     float = 0.01							)					->     List[str]:
							from matplotlib import pyplot as plt  # type: ignore

							a    =			[]  # x coordinates of points to plot
							a    =			[]  # y coordinates of points to plot

							a    =			0.0
							while t <= 1:
										a    =			self.bezier_curve_function(__lowerCamelCase							)
										to_plot_x.append(value[0]							)
										to_plot_y.append(value[1]							)
										t += step_size

							a    =			[i[0] for i in self.list_of_points]
							a    =			[i[1] for i in self.list_of_points]

							plt.plot(
							    __lowerCamelCase					,      __lowerCamelCase					,      color="blue"					,      label="Curve of Degree " + str(self.degree							)					,      )
							plt.scatter(__lowerCamelCase					,      __lowerCamelCase					,      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






