-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday10.odin
115 lines (95 loc) · 2.19 KB
/
day10.odin
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
package day10
import "core:fmt"
import "core:os"
import "core:slice"
import "core:strconv"
import "core:strings"
main :: proc() {
content, ok := os.read_entire_file("input/day10.txt")
if !ok {
// could not read file
return
}
defer delete(content)
lines := strings.split_lines(string(content))
area_arr := make([]int, len(strings.join(lines, "")))
for line, i in lines {
for char, j in line {
area_arr[i * len(lines) + j] = strconv.atoi(fmt.aprint(char))
}
}
area := Area{area_arr, len(lines[0]), len(lines)}
trailheads := make(map[Pos]int)
for y in 0..<area.height {
for x in 0..<area.width {
p := get(area, x, y) or_else -1
if p == 0 {
trailheads[Pos{x, y}] = 0
}
}
}
total_score := 0
total_rating := 0
for trailhead in slice.map_keys(trailheads) or_else nil {
score, rating := find_trails(area, trailhead)
total_score += score
total_rating += rating
}
// Part 1
fmt.println(total_score)
// Part 2
fmt.println(total_rating)
}
Area :: struct {
arr: []int,
width: int,
height: int,
}
Pos :: struct {
x: int,
y: int,
}
get :: proc(area: Area, x: int, y: int) -> (int, bool) {
if x < 0 || x >= area.width || y < 0 || y >= area.height {
return ' ', false
}
return area.arr[y * area.width + x], true
}
neighbours :: proc(pos: Pos) -> [4]Pos {
return [4]Pos{
Pos{pos.x, pos.y - 1},
Pos{pos.x + 1, pos.y},
Pos{pos.x, pos.y + 1},
Pos{pos.x - 1, pos.y},
}
}
find_trails :: proc(area: Area, trailhead: Pos) -> (int, int) {
frontier := make([dynamic]Pos)
append(&frontier, trailhead)
reached := make(map[Pos]int)
reached[trailhead] = 0
trailtops := make(map[Pos]bool)
for len(frontier) > 0 {
current := pop(&frontier)
current_value, current_ok := get(area, current.x, current.y)
if current_value == 9 {
trailtops[current] = true
continue
}
for next in neighbours(current) {
next_value, next_ok := get(area, next.x, next.y)
if next_ok && next_value == current_value + 1 {
if !(next in reached) {
reached[next] = 0
}
append(&frontier, next)
reached[next] += 1
}
}
}
result := 0
for trailtop in slice.map_keys(trailtops) or_else nil {
result += reached[trailtop]
}
return len(trailtops), result
}