adventofcode/2024/day06/main.go

149 lines
3.1 KiB
Go
Raw Normal View History

2024-12-07 14:09:00 +00:00
package main
import (
"fmt"
"time"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToCoordMap()
cp := inp.Copy()
m := part1(inp)
part2(*cp, m.FindAll('X'))
}
var debug = false
func part1(m h.CoordByteMap) h.CoordByteMap {
init, err := m.FindFirst('^')
h.CheckErr(err)
for moveGuard(m) {
if debug {
fmt.Println(h.CLEAR_SCREEN)
fmt.Println(m)
guard := m.FindAll('^', '>', 'v', '<')[0]
fmt.Println(guard)
time.Sleep(time.Second / 10)
}
}
fmt.Println()
fmt.Println("# Part 1")
fmt.Printf("Guard moved into %d positions.\n", m.Count('X'))
fmt.Println()
m.Put(init, '^')
return m
}
func part2(clean h.CoordByteMap, p []h.Coordinate) {
// m should have all of the 'X' spots where the guard moved in part 1
init, err := clean.FindFirst('^')
h.CheckErr(err)
var obstacles []h.Coordinate
for i := range p {
fmt.Println(h.CLEAR_SCREEN)
fmt.Print("Progress: ")
h.PrintProgress(i, len(p))
fmt.Printf(" %d/%d\n", i, len(p))
m := *clean.Copy()
// Try putting an obstacle at p[i]
m.Put(p[i], 'O')
history := make(map[h.Coordinate][]string)
guard := m.FindAll('^', '>', 'v', '<')[0]
tst := m.Get(guard)
history[guard] = append(history[guard], string(tst))
var foundLoop bool
for moveGuard(m) && !foundLoop {
// fmt.Print(".")
if debug {
fmt.Println(h.CLEAR_SCREEN)
fmt.Println(m)
guard := m.FindAll('^', '>', 'v', '<')[0]
fmt.Printf("Guard: %s - Testing Obstacle: %s\n", guard, p[i])
fmt.Println(obstacles)
fmt.Println(history)
time.Sleep(time.Second / 10)
}
guard := m.FindAll('^', '>', 'v', '<')[0]
bt := m.Get(guard)
// Check if we already have this position/orientation in our history
for j := range history[guard] {
if history[guard][j] == string(bt) {
if !contains(obstacles, p[i]) {
obstacles = append(obstacles, p[i])
foundLoop = true
if debug {
fmt.Println("Found Loop:", string(history[guard][j]), "==", string(bt))
}
break
}
}
}
history[guard] = append(history[guard], string(bt))
}
m.Put(p[i], '.')
m.Put(init, '^')
}
fmt.Println()
fmt.Println("# Part 2")
fmt.Printf("Obstacle positions to create a loop: %d\n", len(obstacles))
// 583 is too low
}
func checkForLoop(m h.CoordByteMap) {
}
func contains(sl []h.Coordinate, c h.Coordinate) bool {
for i := range sl {
if sl[i].Equals(c) {
return true
}
}
return false
}
func turn(g byte) byte {
switch g {
case '^':
return '>'
case '>':
return 'v'
case 'v':
return '<'
default:
return '^'
}
}
func nextPos(guard h.Coordinate, m h.CoordByteMap) h.Coordinate {
switch m.Get(guard) {
case '>':
return guard.East()
case 'v':
return guard.South()
case '<':
return guard.West()
}
return guard.North()
}
func moveGuard(m h.CoordByteMap) bool {
guard := m.FindAll('^', '>', 'v', '<')[0]
currBt := m.Get(guard)
turn := turn(currBt)
next := nextPos(guard, m)
if !m.ContainsCoord(next) {
m.Put(guard, 'X')
return false
}
tst := m.Get(next)
if tst == '#' || tst == 'O' {
m.Put(guard, turn)
return moveGuard(m)
}
m.Put(guard, 'X')
m.Put(next, currBt)
return true
}