97 lines
1.9 KiB
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
|
|
}
|