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 }