-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.go
130 lines (116 loc) · 3.42 KB
/
day9.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"sort"
"strconv"
)
func calcBasinSize(lines []string) int {
heightMap := buildHeightMap(lines)
basins := make(map[int]int)
for i := -1; true; i-- {
var newBasinMark = markNewBasin(heightMap, i)
if newBasinMark == 0 {
break
}
basins[newBasinMark]++
markAllAdjacents(heightMap, newBasinMark, basins)
}
basinValues := sortDescBySum(basins)
var sum = 1
for i := 0; i < 3; i++ {
sum *= basinValues[i]
}
return sum
}
func sortDescBySum(basins map[int]int) []int {
var basinValues []int
for _, v := range basins {
basinValues = append(basinValues, v)
}
sort.Ints(basinValues)
for i, j := 0, len(basinValues)-1; i < j; i, j = i+1, j-1 {
basinValues[i], basinValues[j] = basinValues[j], basinValues[i]
}
return basinValues
}
func markAllAdjacents(heightMap [][]int, newBasinMark int, basins map[int]int) {
isUpBasin := func(r int, c int, heightMap [][]int, newBasinMark int) bool {
return r != 0 && heightMap[r-1][c] == newBasinMark
}
isDownBasin := func(r int, c int, heightMap [][]int, newBasinMark int) bool {
return r != len(heightMap)-1 && heightMap[r+1][c] == newBasinMark
}
isLeftBasin := func(r int, c int, heightMap [][]int, newBasinMark int) bool {
return c != 0 && heightMap[r][c-1] == newBasinMark
}
isRightBasin := func(r int, c int, heightMap [][]int, newBasinMark int) bool {
return c != len(heightMap[r])-1 && heightMap[r][c+1] == newBasinMark
}
for true {
notFound := true
for r := 0; r < len(heightMap); r++ {
for c := 0; c < len(heightMap[r]); c++ {
if heightMap[r][c] != 9 && heightMap[r][c] != newBasinMark {
if isUpBasin(r, c, heightMap, newBasinMark) ||
isDownBasin(r, c, heightMap, newBasinMark) ||
isLeftBasin(r, c, heightMap, newBasinMark) ||
isRightBasin(r, c, heightMap, newBasinMark) {
heightMap[r][c] = newBasinMark
basins[newBasinMark]++
notFound = false
}
}
}
}
if notFound {
break
}
}
}
func markNewBasin(heightMap [][]int, i int) int {
for r := 0; r < len(heightMap); r++ {
for c := 0; c < len(heightMap[r]); c++ {
if heightMap[r][c] >= 0 && heightMap[r][c] != 9 {
heightMap[r][c] = i
return heightMap[r][c]
}
}
}
return 0
}
func calcLowPointRisk(lines []string) int {
heightMap := buildHeightMap(lines)
var sum int = 0
for row, v := range heightMap {
for column, cell := range v {
isUpHigher := func(r int, c int, heightMap [][]int, cell int) bool {
return row == 0 || heightMap[row-1][column] > cell
}
isDownHigher := func(r int, c int, heightMap [][]int, cell int) bool {
return row == len(heightMap)-1 || heightMap[row+1][column] > cell
}
isLeftHigher := func(r int, c int, heightMap [][]int, cell int) bool {
return column == 0 || heightMap[row][column-1] > cell
}
isRightHigher := func(r int, c int, heightMap [][]int, cell int) bool {
return column == len(heightMap[row])-1 || heightMap[row][column+1] > cell
}
if isUpHigher(row, column, heightMap, cell) &&
isDownHigher(row, column, heightMap, cell) &&
isLeftHigher(row, column, heightMap, cell) &&
isRightHigher(row, column, heightMap, cell) {
sum += cell + 1
}
}
}
return sum
}
func buildHeightMap(lines []string) [][]int {
var heightMap [][]int = make([][]int, len(lines))
for row, v := range lines {
for i := 0; i < len(v); i++ {
var number, _ = strconv.Atoi(string(v[i]))
heightMap[row] = append(heightMap[row], number)
}
}
return heightMap
}