





"""simple docstring"""




from __future__ import annotations

import random

from matplotlib import animation
from matplotlib import pyplot as plt

# Frame rate of the animation
lowerCamelCase_	:		int         =   20

# Time between time steps in seconds
lowerCamelCase_	:		Optional[Any]         =   INTERVAL / 10_00

class 					_UpperCAmelCase    :



      '''simple docstring'''

      def __init__(	self   , snake_case_   , snake_case_   , snake_case_   , snake_case_   , snake_case_ = 1.0   , snake_case_ = 1.0   , snake_case_ = "blue"   , ):

        """simple docstring"""

        A_    :			str									=    position_x
        A_    :			List[Any]									=    position_y
        A_    :			List[str]									=    velocity_x
        A_    :			str									=    velocity_y
        A_    :			Tuple									=    mass
        A_    :			int									=    size
        A_    :			Optional[int]									=    color

      @property
      def    lowerCamelCase_     (	self    ):

        """simple docstring"""

        return self.position_x, self.position_y

      @property
      def    lowerCamelCase_     (	self    ):

        """simple docstring"""

        return self.velocity_x, self.velocity_y

      def    lowerCamelCase_     (	self   , snake_case_   , snake_case_   , snake_case_    ):

        """simple docstring"""

        self.velocity_x += force_x * delta_time
        self.velocity_y += force_y * delta_time

      def    lowerCamelCase_     (	self   , snake_case_    ):

        """simple docstring"""

        self.position_x += self.velocity_x * delta_time
        self.position_y += self.velocity_y * delta_time


class 					_UpperCAmelCase    :



      '''simple docstring'''

      def __init__(	self   , snake_case_   , snake_case_ = 1.0   , snake_case_ = 1.0   , snake_case_ = 0.0   , ):

        """simple docstring"""

        A_    :			List[Any]									=    bodies
        A_    :			Union[str, Any]									=    gravitation_constant
        A_    :			Dict									=    time_factor
        A_    :			Optional[int]									=    softening_factor

      def __len__(	self    ):

        """simple docstring"""

        return len(self.bodies    )

      def    lowerCamelCase_     (	self   , snake_case_    ):

        """simple docstring"""

        for bodya in self.bodies:
          A_    :			List[str]									=    0.0
          A_    :			Optional[Any]									=    0.0
          for bodya in self.bodies:
            if bodya != bodya:
              A_    :			Union[str, Any]									=    bodya.position_x - bodya.position_x
              A_    :			Dict									=    bodya.position_y - bodya.position_y

              # Calculation of the distance using Pythagoras's theorem
              # Extra factor due to the softening technique
              A_    :			int									=    (dif_x**2 + dif_y**2 + self.softening_factor) ** (
                  1 / 2
              )

              # Newton's law of universal gravitation.
              force_x += (
                  self.gravitation_constant * bodya.mass * dif_x / distance**3
              )
              force_y += (
                  self.gravitation_constant * bodya.mass * dif_y / distance**3
              )

            # Update the body's velocity once all the force components have been added
          bodya.update_velocity(snake_case_   , snake_case_   , delta_time * self.time_factor    )

        # Update the positions only after all the velocities have been updated
        for body in self.bodies:
          body.update_position(delta_time * self.time_factor    )





def 		UpperCAmelCase__						(	_UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase   ):






  """simple docstring"""





  body_system.update_system(_UpperCAmelCase   )

  # Update the positions of the patches
  for patch, body in zip(_UpperCAmelCase					,   body_system.bodies   ):
    A_    :			Optional[Any]									=    (body.position_x, body.position_y)





def 		UpperCAmelCase__						(	_UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase = -1					,   _UpperCAmelCase = 1					,   _UpperCAmelCase = -1					,   _UpperCAmelCase = 1					,   ):






  """simple docstring"""





  A_    :			Dict									=    plt.figure()
  fig.canvas.set_window_title(_UpperCAmelCase   )
  A_    :			Tuple									=    plt.axes(
      xlim=(x_start, x_end)					,   ylim=(y_start, y_end)   )  # Set section to be plotted
  plt.gca().set_aspect('equal'   )  # Fix aspect ratio

  # Each body is drawn as a patch by the plt-function
  A_    :			Tuple									=    [
      plt.Circle((body.position_x, body.position_y)					,   body.size					,   fc=body.color   )
      for body in body_system.bodies
  ]

  for patch in patches:
    ax.add_patch(_UpperCAmelCase   )

  # Function called at each step of the animation
  def update(_UpperCAmelCase   ) -> list[plt.Circle]:
    update_step(_UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase   )
    return patches

  A_    :			Dict									=    animation.FuncAnimation(  # noqa: F841
      _UpperCAmelCase					,   _UpperCAmelCase					,   interval=_UpperCAmelCase					,   blit=_UpperCAmelCase   )

  plt.show()





def 		UpperCAmelCase__						(	):






  """simple docstring"""





  A_    :			List[Any]									=    0.9_700_436
  A_    :			Optional[int]									=    -0.24_308_753
  A_    :			Dict									=    0.466_203_685
  A_    :			Optional[int]									=    0.43_236_573

  A_    :			Union[str, Any]									=    [
      Body(_UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   _UpperCAmelCase					,   size=0.2					,   color='red'   ),
      Body(-position_x					,   -position_y					,   _UpperCAmelCase					,   _UpperCAmelCase					,   size=0.2					,   color='green'   ),
      Body(0					,   0					,   -2 * velocity_x					,   -2 * velocity_y					,   size=0.2					,   color='blue'   ),
  ]
  return BodySystem(_UpperCAmelCase					,   time_factor=3   )





def 		UpperCAmelCase__						(	):






  """simple docstring"""





  A_    :			int									=    7.34_76E22
  A_    :			Union[str, Any]									=    5.9_72E24
  A_    :			Dict									=    1022
  A_    :			Optional[int]									=    384399000
  A_    :			List[str]									=    6.6_74E-11

  # Calculation of the respective velocities so that total impulse is zero,
  # i.e. the two bodies together don't move
  A_    :			Tuple									=    earth_mass * velocity_dif / (earth_mass + moon_mass)
  A_    :			Dict									=    moon_velocity - velocity_dif

  A_    :			Optional[int]									=    Body(-earth_moon_distance					,   0					,   0					,   _UpperCAmelCase					,   _UpperCAmelCase					,   10000000					,   'grey'   )
  A_    :			Optional[Any]									=    Body(0					,   0					,   0					,   _UpperCAmelCase					,   _UpperCAmelCase					,   50000000					,   'blue'   )
  return BodySystem([earth, moon]					,   _UpperCAmelCase					,   time_factor=1000000   )





def 		UpperCAmelCase__						(	):






  """simple docstring"""





  A_    :			Optional[Any]									=    []
  for _ in range(10   ):
    A_    :			Union[str, Any]									=    random.uniform(-0.5					,   0.5   )
    A_    :			List[str]									=    random.uniform(-0.5					,   0.5   )

    # Bodies are created pairwise with opposite velocities so that the
    # total impulse remains zero
    bodies.append(
        Body(
            random.uniform(-0.5					,   0.5   )					,   random.uniform(-0.5					,   0.5   )					,   _UpperCAmelCase					,   _UpperCAmelCase					,   size=0.05					,   )   )
    bodies.append(
        Body(
            random.uniform(-0.5					,   0.5   )					,   random.uniform(-0.5					,   0.5   )					,   -velocity_x					,   -velocity_y					,   size=0.05					,   )   )
  return BodySystem(_UpperCAmelCase					,   0.01					,   10					,   0.1   )


if __name__ == "__main__":
   plot('Figure-8 solution to the 3-body-problem', example_a(), -2, 2, -2, 2)
   plot(
       'Moon\'s orbit around the earth',
       example_a(),
       -4_30_00_00_00,
       4_30_00_00_00,
       -4_30_00_00_00,
       4_30_00_00_00,
   )
   plot('Random system with many bodies', example_a(), -1.5, 1.5, -1.5, 1.5)




from __future__ import annotations





def 		__snake_case						(    _UpperCAmelCase       ,			_UpperCAmelCase       ,			_UpperCAmelCase				):
					"""simple docstring"""






					assert (
					    c % greatest_common_divisor(_UpperCAmelCase       ,			_UpperCAmelCase				) == 0
					)  # greatest_common_divisor(a,b) function implemented below
					((lowercase)   ,      (lowercase)   ,      (lowercase))						   =       extended_gcd(_UpperCAmelCase       ,			_UpperCAmelCase				)  # extended_gcd(a,b) function implemented below
					lowercase						   =       c / d
					return (r * x, r * y)





def 		__snake_case						(    _UpperCAmelCase       ,			_UpperCAmelCase       ,			_UpperCAmelCase       ,			_UpperCAmelCase = 2				):
					"""simple docstring"""






					((lowercase)   ,      (lowercase))						   =       diophantine(_UpperCAmelCase       ,			_UpperCAmelCase       ,			_UpperCAmelCase				)  # Initial value
					lowercase						   =       greatest_common_divisor(_UpperCAmelCase       ,			_UpperCAmelCase				)
					lowercase						   =       a // d
					lowercase						   =       b // d

					for i in range(_UpperCAmelCase				):
										lowercase						   =       xa + i * q
										lowercase						   =       ya - i * p
										print(_UpperCAmelCase       ,			_UpperCAmelCase				)





def 		__snake_case						(    _UpperCAmelCase       ,			_UpperCAmelCase				):
					"""simple docstring"""






					if a < b:
										lowercase   ,      lowercase						   =       b, a

					while a % b != 0:
										lowercase   ,      lowercase						   =       b, a % b

					return b





def 		__snake_case						(    _UpperCAmelCase       ,			_UpperCAmelCase				):
					"""simple docstring"""






					assert a >= 0 and b >= 0

					if b == 0:
										lowercase   ,      lowercase   ,      lowercase						   =       a, 1, 0
					else:
										((lowercase)   ,      (lowercase)   ,      (lowercase))						   =       extended_gcd(_UpperCAmelCase       ,			a % b				)
										lowercase						   =       q
										lowercase						   =       p - q * (a // b)

					assert a % d == 0 and b % d == 0
					assert d == a * x + b * y

					return (d, x, y)


if __name__ == "__main__":
		from doctest import testmod

		testmod(name='''diophantine''', verbose=True)
		testmod(name='''diophantine_all_soln''', verbose=True)
		testmod(name='''extended_gcd''', verbose=True)
		testmod(name='''greatest_common_divisor''', verbose=True)






