package main import ( "fmt" helpers "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := helpers.StdinToStringSlice() part1(inp) part2(inp) } func part1(inp []string) { s := NewSystem(inp) for i := 1; i <= 1000; i++ { s.Step() } fmt.Println("System Energy:", s.GetTotalEnergy()) } func part2(inp []string) { s := NewSystem(inp) sInit := NewSystem(inp) // Find how long it takes for all planets to repeat done := make([]bool, 3) count := make([]int, 3) for !AllTrue(done...) { s.Step() for i := 0; i < len(done); i++ { if !done[i] { equal := true for pi := range s.moons { switch i { case 0: if s.moons[pi].posX != sInit.moons[pi].posX || s.moons[pi].velX != sInit.moons[pi].velX { equal = false } case 1: if s.moons[pi].posY != sInit.moons[pi].posY || s.moons[pi].velY != sInit.moons[pi].velY { equal = false } case 2: if s.moons[pi].posZ != sInit.moons[pi].posZ || s.moons[pi].velZ != sInit.moons[pi].velZ { equal = false } } } if equal { done[i] = true } else { count[i]++ } } } } fmt.Println(count[0], count[1], count[2]) fmt.Println(helpers.Lcm(count[0]+1, count[1]+1, count[2]+1)) } func AllTrue(done ...bool) bool { for _, v := range done { if !v { return false } } return true } type System struct { moons []*Moon } func NewSystem(inp []string) *System { s := &System{} for k := range inp { var x, y, z int _, err := fmt.Sscanf(inp[k], "", &x, &y, &z) if err != nil { panic(err) } s.AddMoon(NewMoon(x, y, z)) } return s } func (s *System) AddMoon(m *Moon) { s.moons = append(s.moons, m) } func (s *System) Step() { for i := range s.moons { for j := i + 1; j < len(s.moons); j++ { s.moons[i].Interact(s.moons[j]) } } for i := range s.moons { s.moons[i].Step() } } func (s *System) GetTotalEnergy() int { var ret int for v := range s.moons { ret = ret + (s.moons[v].GetPotentialEnergy() * s.moons[v].GetKineticEnergy()) } return ret } func (s System) String() string { var ret string for k := range s.moons { ret = ret + s.moons[k].String() + "\n" } return ret } type Moon struct { posX, posY, posZ int velX, velY, velZ int } func NewMoon(x, y, z int) *Moon { return &Moon{ posX: x, posY: y, posZ: z, } } func (m *Moon) GetPotentialEnergy() int { return helpers.AbsInt(m.posX) + helpers.AbsInt(m.posY) + helpers.AbsInt(m.posZ) } func (m *Moon) GetKineticEnergy() int { return helpers.AbsInt(m.velX) + helpers.AbsInt(m.velY) + helpers.AbsInt(m.velZ) } func (m *Moon) Interact(n *Moon) { if n.posX > m.posX { n.velX-- m.velX++ } else if n.posX < m.posX { n.velX++ m.velX-- } if n.posY > m.posY { n.velY-- m.velY++ } else if n.posY < m.posY { n.velY++ m.velY-- } if n.posZ > m.posZ { n.velZ-- m.velZ++ } else if n.posZ < m.posZ { n.velZ++ m.velZ-- } } func (m *Moon) Step() { m.posX += m.velX m.posY += m.velY m.posZ += m.velZ } func (m *Moon) PosEquals(n *Moon) (bool, bool, bool) { return (m.posX == n.posX), (m.posY == n.posY), (m.posZ == n.posZ) } func (m Moon) String() string { return fmt.Sprintf("pos=, vel=", m.posX, m.posY, m.posZ, m.velX, m.velY, m.velZ, ) }