adventofcode/2021/day09/main.go

97 lines
1.9 KiB
Go

package main
import (
"fmt"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
m := h.StringSliceToCoordByteMap(inp)
findBasins(m, findLowestPoints(m))
}
func findLowestPoints(m h.CoordByteMap) []h.Coordinate {
var points []h.Coordinate
var low []int
for y := 0; y < m.Height; y++ {
for x := 0; x < m.Width; x++ {
c := h.Coordinate{X: x, Y: y}
v := m.Get(c)
if y > 0 { // Check North
if m.Get(c.North()) <= v {
continue
}
}
if y < m.Height-1 { // Check South
if m.Get(c.South()) <= v {
continue
}
}
if x > 0 { // Check West
if m.Get(c.West()) <= v {
continue
}
}
if x < m.Width-1 { // Check East
if m.Get(c.East()) <= v {
continue
}
}
points = append(points, c)
low = append(low, btoi(v))
}
}
fmt.Println()
fmt.Println("# Part 1")
var tot int
for i := range low {
tot += low[i] + 1
}
fmt.Println("Total Risk Level:", tot)
return points
}
func findBasins(m h.CoordByteMap, lows []h.Coordinate) {
basins := make(map[h.Coordinate]int)
for i := range lows {
basins[lows[i]], _ = findBasinSize(m, lows[i], make(map[h.Coordinate]bool))
}
// Find the three largest
one := h.MIN_INT
two := h.MIN_INT
three := h.MIN_INT
for _, v := range basins {
if v > one {
one, two, three = v, one, two
} else if v > two {
two, three = v, two
} else if v > three {
three = v
}
}
fmt.Println()
fmt.Println("# Part 2")
fmt.Println("Total:", (one * two * three))
}
func findBasinSize(m h.CoordByteMap, low h.Coordinate, checked map[h.Coordinate]bool) (int, map[h.Coordinate]bool) {
size := 1
checked[low] = true
for _, v := range []h.Coordinate{low.North(), low.East(), low.South(), low.West()} {
if m.Get(v) != 0 && !checked[v] && btoi(m.Get(v)) < 9 {
var s int
s, checked = findBasinSize(m, v, checked)
size += s
}
}
return size, checked
}
func btoi(b byte) int {
return int(b) - 48
}