adventofcode/2024/day14/main.go

165 lines
3.1 KiB
Go

package main
import (
"fmt"
"math"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
fmt.Println()
part2(inp)
}
func part1(inp []string) {
fmt.Println("# Part 1")
// Main Input size
sizeX, sizeY := 101, 103
bots := parseInput(inp, sizeX, sizeY)
for i := 0; i < 100; i++ {
for j := range bots {
bots[j].Move()
}
}
for i := range bots {
fmt.Println(bots[i])
}
qCnt := make([]int, 4)
for y := 0; y < sizeY; y++ {
for x := 0; x < sizeX; x++ {
if x == sizeX/2 || y == sizeY/2 {
fmt.Print(" ")
continue
}
bCnt := 0
for i := range bots {
if x == bots[i].X && y == bots[i].Y {
bCnt++
if x < sizeX/2 {
if y < sizeY/2 {
qCnt[0]++
} else {
qCnt[2]++
}
} else {
if y < sizeY/2 {
qCnt[1]++
} else {
qCnt[3]++
}
}
}
}
if bCnt > 0 {
fmt.Print(bCnt)
} else {
fmt.Print(".")
}
}
fmt.Println()
}
fmt.Println("Safety Factor:", (qCnt[0] * qCnt[1] * qCnt[2] * qCnt[3]))
}
func part2(inp []string) {
fmt.Println("# Part 2")
// Main Input size
sizeX, sizeY := 101, 103
bots := parseInput(inp, sizeX, sizeY)
printState := func() {
for y := 0; y < sizeY; y++ {
for x := 0; x < sizeX; x++ {
btCnt := 0
for _, b := range bots {
if b.X == x && b.Y == y {
btCnt++
}
}
if btCnt == 0 {
fmt.Print(".")
} else if btCnt < 10 {
fmt.Print(btCnt)
} else {
fmt.Print("#")
}
}
fmt.Println()
}
}
// My hypothesis: most bots will be close to each other for the answer
lowest := h.MAX_INT
var lowStdX, lowStdY float64
for steps := 0; steps < 10000000; steps++ {
xs := make([]int, 0, len(bots))
ys := make([]int, 0, len(bots))
for j := range bots {
bots[j].Move()
xs = append(xs, bots[j].X)
ys = append(ys, bots[j].Y)
}
// After finding it, I added this to print it out :D
if steps == 7036 {
printState()
}
wrkX, wrkY := stdev(xs), stdev(ys)
if lowest == h.MAX_INT || (wrkX < lowStdX && wrkY < lowStdY) {
fmt.Println(lowest, ":", lowStdX, lowStdY)
lowStdX, lowStdY, lowest = wrkX, wrkY, steps
}
}
fmt.Println("Steps to Easter Egg:", lowest)
}
func stdev(vals []int) float64 {
m := 0.0
for _, w := range vals {
m += float64(w)
}
m /= float64(len(vals))
v := 0.0
for _, w := range vals {
diff := float64(w) - m
v += diff * diff
}
return math.Sqrt(v / float64(len(vals)))
}
var botRaw = "p=%d,%d v=%d,%d"
type Bot struct {
X, Y, Vx, Vy int
mX, mY int
}
func NewBot(inp string) *Bot {
b := Bot{}
fmt.Sscanf(inp, botRaw, &b.X, &b.Y, &b.Vx, &b.Vy)
return &b
}
func (b *Bot) Move() {
b.X = (b.X + b.Vx + b.mX) % b.mX
b.Y = (b.Y + b.Vy + b.mY) % b.mY
}
func (b *Bot) Overlaps(bt *Bot) bool {
return b.X == bt.X && b.Y == bt.Y
}
func (b Bot) String() string {
return fmt.Sprintf(botRaw, b.X, b.Y, b.Vx, b.Vy)
}
func parseInput(inp []string, mX, mY int) []*Bot {
var ret []*Bot
for i := range inp {
b := NewBot(inp[i])
b.mX, b.mY = mX, mY
ret = append(ret, b)
}
return ret
}