Watch
1
0
Fork
You've already forked advent-of-code
0
advent-of-code/2021/day9/main.go
2021-12-08 21:45:23 -08:00

110 lines
1.7 KiB
Go

package main
import (
"fmt"
"sort"
"github.com/jdkaplan/advent-of-code/aoc"
)
func main() {
lines := aoc.Input().ReadLines("day9.txt")
fmt.Println(part1(lines))
fmt.Println(part2(lines))
}
func part1(lines []string) (risk int) {
g := NewGrid(lines)
for r := 0; r < g.Rows; r++ {
for c := 0; c < g.Cols; c++ {
risk += g.Risk(r, c)
}
}
return risk
}
func part2(lines []string) int {
g := NewGrid(lines)
var starts []RC
for r := 0; r < g.Rows; r++ {
for c := 0; c < g.Cols; c++ {
if g.Risk(r, c) != 0 {
starts = append(starts, RC{r, c})
}
}
}
var sizes []int
for _, rc := range starts {
sizes = append(sizes, g.Flood(rc))
}
sort.Sort(sort.Reverse(sort.IntSlice(sizes)))
return sizes[0] * sizes[1] * sizes[2]
}
type RC struct{ r, c int }
type Grid struct {
Rows int
Cols int
m map[RC]int
}
func NewGrid(lines []string) Grid {
g := Grid{
m: make(map[RC]int),
Rows: len(lines),
Cols: len(lines[0]),
}
for r, row := range lines {
for c, col := range row {
g.m[RC{r, c}] = int(col - '0')
}
}
return g
}
func (g Grid) Risk(r, c int) int {
rc := RC{r, c}
v, ok := g.m[rc]
if !ok {
return 0
}
for _, n := range g.Neighbors(rc) {
u, ok := g.m[n]
if ok && u <= v {
return 0
}
}
return v + 1
}
func (g Grid) Neighbors(rc RC) []RC {
r, c := rc.r, rc.c
return []RC{
{r - 1, c},
{r, c + 1},
{r + 1, c},
{r, c - 1},
}
}
func (g Grid) Flood(rc RC) (size int) {
queue := []RC{rc}
seen := make(map[RC]bool)
for len(queue) > 0 {
rc, queue = queue[0], queue[1:]
if seen[rc] {
continue
}
for _, n := range g.Neighbors(rc) {
if v, ok := g.m[n]; ok && v < 9 {
queue = append(queue, n)
}
}
seen[rc] = true
size++
}
return size
}