2021 Day 15 Complete!
This commit is contained in:
144
2021/day15/main.go
Normal file
144
2021/day15/main.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
var cave h.CoordByteMap
|
||||
var debug bool
|
||||
|
||||
func main() {
|
||||
debug = len(os.Args) > 1 && os.Args[1] == "--debug"
|
||||
inp := h.StdinToStringSlice()
|
||||
cave = h.StringSliceToCoordByteMap(inp)
|
||||
fmt.Println("# Part 1")
|
||||
part1()
|
||||
fmt.Println("# Part 2")
|
||||
part2()
|
||||
}
|
||||
|
||||
var visited map[h.Coordinate]bool
|
||||
var distance map[h.Coordinate]int
|
||||
var curr h.Coordinate
|
||||
|
||||
func part1() {
|
||||
distance = make(map[h.Coordinate]int)
|
||||
visited = make(map[h.Coordinate]bool)
|
||||
for k := range cave.Field {
|
||||
visited[k] = false
|
||||
distance[k] = h.MAX_INT
|
||||
}
|
||||
curr = h.Coordinate{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
}
|
||||
distance[curr] = 0
|
||||
visited[curr] = true
|
||||
|
||||
work()
|
||||
fmt.Println(distance[h.Coordinate{X: cave.Width - 1, Y: cave.Height - 1}])
|
||||
}
|
||||
|
||||
func work() {
|
||||
// Find the unvisited node with the smallest tentative distance
|
||||
var c h.Coordinate
|
||||
cDist := h.MAX_INT
|
||||
for k, v := range distance {
|
||||
if visited[k] {
|
||||
continue
|
||||
}
|
||||
if v < cDist {
|
||||
cDist = v
|
||||
c = k
|
||||
}
|
||||
}
|
||||
|
||||
check := getNeighbors(c)
|
||||
for _, v := range check {
|
||||
if !visited[v] {
|
||||
if b, ok := distance[v]; !ok || b > distance[c]+getInt(v) {
|
||||
distance[v] = distance[c] + getInt(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
visited[c] = true
|
||||
|
||||
// if we still have unvisited nodes, recurse
|
||||
if moreWork() {
|
||||
work()
|
||||
}
|
||||
}
|
||||
|
||||
func moreWork() bool {
|
||||
for i := range visited {
|
||||
if visited[i] == false {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func part2() {
|
||||
// Build the full cave
|
||||
expandCave(5)
|
||||
part1()
|
||||
}
|
||||
|
||||
func getInt(c h.Coordinate) int {
|
||||
return int(cave.Opt(c, '0')) - int('0')
|
||||
}
|
||||
|
||||
func getNeighbors(c h.Coordinate) []h.Coordinate {
|
||||
var ret []h.Coordinate
|
||||
for _, n := range []h.Coordinate{c.North(), c.East(), c.South(), c.West()} {
|
||||
if v := cave.Opt(n, 'Z'); v != 'Z' {
|
||||
ret = append(ret, n)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func expandCave(size int) {
|
||||
oH, oW := cave.Height, cave.Width
|
||||
for i := 1; i < size; i++ {
|
||||
for y := 0; y < oH; y++ {
|
||||
for x := 0; x < oW; x++ {
|
||||
ny := (oH*i + y)
|
||||
prev := h.Coordinate{
|
||||
X: x,
|
||||
Y: (oH*(i-1) + y),
|
||||
}
|
||||
pv := cave.Get(prev)
|
||||
var v byte
|
||||
if pv == '9' {
|
||||
v = '1'
|
||||
} else {
|
||||
v = pv + 1
|
||||
}
|
||||
cave.Put(h.Coordinate{X: x, Y: ny}, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
for y := 0; y < cave.Height; y++ {
|
||||
for i := 1; i < size; i++ {
|
||||
for x := 0; x < oW; x++ {
|
||||
nx := (oW*i + x)
|
||||
prev := h.Coordinate{
|
||||
X: (oW*(i-1) + x),
|
||||
Y: y,
|
||||
}
|
||||
pv := cave.Get(prev)
|
||||
var v byte
|
||||
if pv == '9' {
|
||||
v = '1'
|
||||
} else {
|
||||
v = pv + 1
|
||||
}
|
||||
cave.Put(h.Coordinate{X: nx, Y: y}, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user