code: 
  
  
  from __future__ import annotations
  
  import random
  
  from matplotlib import animation
  from matplotlib import pyplot as plt
  
  # Frame rate of the animation
  A_														=      2_0
  
  # Time between time steps in seconds
  A_														=      INTERVAL / 1_0_0_0
  
  class 						snake_case			:
  			'''simple docstring'''
  
  			def __init__(	self     :     int							,							lowerCAmelCase_     :     Union[str, Any]							,							lowerCAmelCase_     :     int							,							lowerCAmelCase_     :     str							,							lowerCAmelCase_     :     Any							,							lowerCAmelCase_     :     List[str] = 1.0							,							lowerCAmelCase_     :     int = 1.0							,							lowerCAmelCase_     :     Optional[int] = "blue"							,							)					->					str:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								SCREAMING_SNAKE_CASE_	      =       position_x
  								SCREAMING_SNAKE_CASE_	      =       position_y
  								SCREAMING_SNAKE_CASE_	      =       velocity_x
  								SCREAMING_SNAKE_CASE_	      =       velocity_y
  								SCREAMING_SNAKE_CASE_	      =       mass
  								SCREAMING_SNAKE_CASE_	      =       size
  								SCREAMING_SNAKE_CASE_	      =       color
  
  			@property
  			def _lowercase (	self     :     Dict					)					->					Optional[int]:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								return self.position_x, self.position_y
  
  			@property
  			def _lowercase (	self     :     int					)					->					Optional[Any]:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								return self.velocity_x, self.velocity_y
  
  			def _lowercase (	self     :     Optional[Any]							,							lowerCAmelCase_     :     str							,							lowerCAmelCase_     :     Tuple							,							lowerCAmelCase_     :     Dict					)					->					Optional[int]:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								self.velocity_x += force_x * delta_time
  								self.velocity_y += force_y * delta_time
  
  
  
  
  			def _lowercase (	self     :     Optional[int]							,							lowerCAmelCase_     :     Union[str, Any]					)					->					Optional[Any]:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								self.position_x += self.velocity_x * delta_time
  								self.position_y += self.velocity_y * delta_time
  
  class 						snake_case			:
  			'''simple docstring'''
  
  			def __init__(	self     :     int							,							lowerCAmelCase_     :     Any							,							lowerCAmelCase_     :     List[str] = 1.0							,							lowerCAmelCase_     :     int = 1.0							,							lowerCAmelCase_     :     str = 0.0							,							)					->					List[str]:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								SCREAMING_SNAKE_CASE_	      =       bodies
  								SCREAMING_SNAKE_CASE_	      =       gravitation_constant
  								SCREAMING_SNAKE_CASE_	      =       time_factor
  								SCREAMING_SNAKE_CASE_	      =       softening_factor
  
  			def __len__(	self     :     Dict					)					->					Dict:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								return len(self.bodies					)
  
  
  
  
  			def _lowercase (	self     :     List[str]							,							lowerCAmelCase_     :     Optional[Any]					)					->					Dict:
  
  
  
  
  								"""simple docstring"""
  
  
  
  
  
  
  								for bodya in self.bodies:
  													SCREAMING_SNAKE_CASE_	      =       0.0
  													SCREAMING_SNAKE_CASE_	      =       0.0
  													for bodya in self.bodies:
  																		if bodya != bodya:
  																							SCREAMING_SNAKE_CASE_	      =       bodya.position_x - bodya.position_x
  																							SCREAMING_SNAKE_CASE_	      =       bodya.position_y - bodya.position_y
  
  																							# Calculation of the distance using Pythagoras's theorem
  																							# Extra factor due to the softening technique
  																							SCREAMING_SNAKE_CASE_	      =       (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(lowerCamelCase__							,							lowerCamelCase__							,							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      )->		List[str]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					body_system.update_system(UpperCAmelCase      )
  
  					# Update the positions of the patches
  					for patch, body in zip(UpperCAmelCase				,body_system.bodies      ):
  										SCREAMING_SNAKE_CASE_	      =       (body.position_x, body.position_y)
  
  
  
  
  
  
  
  def 							UpperCAmelCase				(     UpperCAmelCase				,UpperCAmelCase				,UpperCAmelCase = -1				,UpperCAmelCase = 1				,UpperCAmelCase = -1				,UpperCAmelCase = 1				,)->		Dict:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					SCREAMING_SNAKE_CASE_	      =       plt.figure()
  					fig.canvas.set_window_title(UpperCAmelCase      )
  					SCREAMING_SNAKE_CASE_	      =       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
  					SCREAMING_SNAKE_CASE_	      =       [
  					    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
  
  					SCREAMING_SNAKE_CASE_	      =       animation.FuncAnimation(  # noqa: F841
  					    UpperCAmelCase				,UpperCAmelCase				,interval=UpperCAmelCase				,blit=UpperCAmelCase      )
  
  					plt.show()
  
  
  
  
  
  
  
  def 							UpperCAmelCase				(     )->		Dict:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					SCREAMING_SNAKE_CASE_	      =       0.9_7_0_0_4_3_6
  					SCREAMING_SNAKE_CASE_	      =       -0.2_4_3_0_8_7_5_3
  					SCREAMING_SNAKE_CASE_	      =       0.4_6_6_2_0_3_6_8_5
  					SCREAMING_SNAKE_CASE_	      =       0.4_3_2_3_6_5_7_3
  
  					SCREAMING_SNAKE_CASE_	      =       [
  					    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				(     )->		List[Any]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					SCREAMING_SNAKE_CASE_	      =       7.3476E22
  					SCREAMING_SNAKE_CASE_	      =       5.972E24
  					SCREAMING_SNAKE_CASE_	      =       1022
  					SCREAMING_SNAKE_CASE_	      =       384399000
  					SCREAMING_SNAKE_CASE_	      =       6.674E-11
  
  					# Calculation of the respective velocities so that total impulse is zero,
  					# i.e. the two bodies together don't move
  					SCREAMING_SNAKE_CASE_	      =       earth_mass * velocity_dif / (earth_mass + moon_mass)
  					SCREAMING_SNAKE_CASE_	      =       moon_velocity - velocity_dif
  
  					SCREAMING_SNAKE_CASE_	      =       Body(-earth_moon_distance				,0				,0				,UpperCAmelCase				,UpperCAmelCase				,10000000				,'''grey'''      )
  					SCREAMING_SNAKE_CASE_	      =       Body(0				,0				,0				,UpperCAmelCase				,UpperCAmelCase				,50000000				,'''blue'''      )
  					return BodySystem([earth, moon]				,UpperCAmelCase				,time_factor=1000000      )
  
  
  
  
  
  
  
  def 							UpperCAmelCase				(     )->		List[str]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					SCREAMING_SNAKE_CASE_	      =       []
  					for _ in range(10      ):
  										SCREAMING_SNAKE_CASE_	      =       random.uniform(-0.5				,0.5      )
  										SCREAMING_SNAKE_CASE_	      =       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.0_5				,)      )
  										bodies.append(
  										    Body(
  										        random.uniform(-0.5				,0.5      )				,random.uniform(-0.5				,0.5      )				,-velocity_x				,-velocity_y				,size=0.0_5				,)      )
  					return BodySystem(UpperCAmelCase				,0.0_1				,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_3_0_0_0_0_0_0_0,
  		    4_3_0_0_0_0_0_0_0,
  		    -4_3_0_0_0_0_0_0_0,
  		    4_3_0_0_0_0_0_0_0,
  		)
  		plot("Random system with many bodies", example_a(), -1.5, 1.5, -1.5, 1.5)
  
  
  
style_context: 
  
  
  def 							UpperCAmelCase				(     UpperCAmelCase      )->		bool:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  					if not isinstance(UpperCAmelCase				,UpperCAmelCase      ):
  										SCREAMING_SNAKE_CASE_	      =       f'''Input value of [number={number}] must be an integer'''
  										raise TypeError(UpperCAmelCase      )
  					if number < 0 or number % 2 == 1:
  										return False
  					SCREAMING_SNAKE_CASE_	      =       int(number**0.5      )
  					return number == number_sqrt * (number_sqrt + 1)
  
  
  if __name__ == "__main__":
  		import doctest
  
  		doctest.testmod()
  
  
  