DEV Community

Discussion on: Advent of Code 2019 Solution Megathread - Day 12: The N-Body Problem

Collapse
 
neilgall profile image
Neil Gall • Edited

Got part 2 in the end! The intuition that each axis is independent came to me while I was away from the keyboard!

def simulate_until_repeat(moons: List[Moon]) -> int:
  """
  Simulate `moons` until a repeated state is seen. Returns the
  number of simulation steps to get to that state
  """
  def gcd(x: int, y: int) -> int:
    return y if x == 0 else gcd(y % x, x)

  def loop_size_for_axis(moons: List[Moon], axis) -> int:
    def state(m: List[Moon]) -> str:
      return str(list(axis(x) for x in m))

    states = set(state(moons))
    for n, m in enumerate(simulate_seq(moons)):
      s = state(m)
      if s in states:
        return n
      states.add(s)

  def axis_x(m): return (m.pos.x, m.velocity.x)
  def axis_y(m): return (m.pos.y, m.velocity.y)
  def axis_z(m): return (m.pos.z, m.velocity.z)

  overall_loop = 1
  for a in [axis_x, axis_y, axis_z]:
    loop = loop_size_for_axis(moons, a)
    overall_loop = overall_loop * loop // gcd(loop, overall_loop)

  return overall_loop