-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday05.go
140 lines (116 loc) · 2.82 KB
/
day05.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
131
132
133
134
135
136
137
138
139
140
package main
import (
_ "embed"
"fmt"
"math"
"strconv"
"strings"
)
//go:embed input.txt
var input string
type rule struct {
start int
end int
shift int
}
func parseSeeds(line string) []int {
var seeds []int
for _, s := range strings.Split(line[7:], " ") {
n, _ := strconv.Atoi(s)
seeds = append(seeds, n)
}
return seeds
}
func parseSeedRanges(line string) [][2]int {
parts := strings.Split(line[7:], " ")
var seeds [][2]int
for i := 0; i < len(parts); i += 2 {
n1, _ := strconv.Atoi(parts[i])
n2, _ := strconv.Atoi(parts[i+1])
seeds = append(seeds, [2]int{n1, n1 + n2 - 1})
}
return seeds
}
func parseMaps(lines []string) [7][]rule {
var maps [7][]rule
var mapIndex int
for _, line := range lines {
if len(line) == 0 {
mapIndex++
} else if line[0] >= '0' && line[0] <= '9' {
var numbers [3]int
for i, s := range strings.Split(line, " ") {
numbers[i], _ = strconv.Atoi(s)
}
maps[mapIndex] = append(maps[mapIndex], rule{
start: numbers[1],
end: numbers[1] + numbers[2],
shift: numbers[0] - numbers[1],
})
}
}
return maps
}
func convertRanges(ranges [][2]int, rules []rule) [][2]int {
var shifted [][2]int
for _, r := range rules {
for i := 0; i < len(ranges); i++ {
n := &ranges[i]
startInside := n[0] >= r.start && n[0] <= r.end
endInside := n[1] >= r.start && n[1] <= r.end
opositeSides := n[0] < r.start && n[1] > r.end
if startInside && endInside {
shifted = append(shifted, [2]int{n[0] + r.shift, n[1] + r.shift})
ranges = append(ranges[:i], ranges[i+1:]...)
i--
} else if opositeSides {
shifted = append(shifted, [2]int{r.start + r.shift, r.end + r.shift})
ranges = append(ranges, [2]int{r.end + 1, n[1]})
*n = [2]int{n[0], r.start - 1}
} else if startInside {
shifted = append(shifted, [2]int{n[0] + r.shift, r.end + r.shift})
*n = [2]int{r.end + 1, n[1]}
} else if endInside {
shifted = append(shifted, [2]int{r.start + r.shift, n[1] + r.shift})
*n = [2]int{n[0], r.start - 1}
}
}
}
return append(shifted, ranges...)
}
func part1(input string) int {
lines := strings.Split(input, "\n")
seeds := parseSeeds(lines[0])
maps := parseMaps(lines[3:])
lowest := math.MaxInt
for _, s := range seeds {
for _, m := range maps {
for _, r := range m {
if s > r.start && s < r.end {
s += r.shift
break
}
}
}
lowest = min(lowest, s)
}
return lowest
}
func part2(input string) int {
lines := strings.Split(input, "\n")
seeds := parseSeedRanges(lines[0])
maps := parseMaps(lines[3:])
for _, m := range maps {
seeds = convertRanges(seeds, m)
}
lowest := seeds[0][0]
for _, s := range seeds {
lowest = min(lowest, s[0])
}
return lowest
}
func main() {
fmt.Println("--- 2023 day 05 answer ---")
fmt.Println("part 1:\t", part1(input))
fmt.Println("part 2:\t", part2(input))
}