adventofcode/2019/day12/main.go

179 lines
3.3 KiB
Go
Raw Normal View History

2019-12-12 14:24:43 +00:00
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=%d, y=%d, z=%d>", &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=<x=%3d, y=%3d, z=%3d>, vel=<x=%3d, y=%3d, z=%3d>",
m.posX, m.posY, m.posZ,
m.velX, m.velY, m.velZ,
)
}