diff --git a/2019/day12/input b/2019/day12/input new file mode 100644 index 0000000..1754c6a --- /dev/null +++ b/2019/day12/input @@ -0,0 +1,4 @@ + + + + diff --git a/2019/day12/main.go b/2019/day12/main.go new file mode 100644 index 0000000..be327ef --- /dev/null +++ b/2019/day12/main.go @@ -0,0 +1,178 @@ +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, + ) +} diff --git a/2019/day12/testinput1 b/2019/day12/testinput1 new file mode 100644 index 0000000..89cc805 --- /dev/null +++ b/2019/day12/testinput1 @@ -0,0 +1,4 @@ + + + + diff --git a/2019/day12/testinput2 b/2019/day12/testinput2 new file mode 100644 index 0000000..aaff01e --- /dev/null +++ b/2019/day12/testinput2 @@ -0,0 +1,4 @@ + + + + diff --git a/helpers/helpers.go b/helpers/helpers.go index 6369216..9a7432a 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -27,6 +27,23 @@ const ( MIN_INT = -MAX_INT - 1 ) +// Find the greatest common denominator +func Gcd(x, y int) int { + for y != 0 { + x, y = y, x%y + } + return x +} + +// Find the least common multiple, using gcd +func Lcm(a, b int, integers ...int) int { + result := a * b / Gcd(a, b) + for i := 0; i < len(integers); i++ { + result = Lcm(result, integers[i]) + } + return result +} + func AbsInt(i int) int { if i < 0 { return i * -1