-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path05p1.go
145 lines (115 loc) · 3.62 KB
/
05p1.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
141
142
143
144
145
package main
import (
"fmt"
"strconv"
"strings"
"aoc2023/utils"
)
type alamanacMap struct {
mapName string
ranges []almanacMapRange
}
type almanacMapRange struct {
destinationRangeStart int
sourceRangeStart int
rangeLength int
}
func D05P1() {
lines := utils.ReadLines("./inputs/05.txt")
seeds := parseAlmanacSeeds(lines)
maps := parseAlmanacMaps(lines)
ranges := []int{}
for i := 0; i < len(seeds); i++ {
ranges = append(ranges, 1)
}
for _, almanacMap := range maps {
mappedSeeds := []int{}
mappedRanges := []int{}
for i, seed := range seeds {
newSeeds, newRanges := applyAlmanacMap(seed, ranges[i], almanacMap)
mappedSeeds = append(mappedSeeds, newSeeds...)
mappedRanges = append(mappedRanges, newRanges...)
}
seeds = mappedSeeds
ranges = mappedRanges
}
lowestLocationNumber := int(^uint(0) >> 1)
for _, seed := range seeds {
if seed < lowestLocationNumber {
lowestLocationNumber = seed
}
}
fmt.Printf("Lowest location number: %d\n", lowestLocationNumber)
}
func parseAlmanacSeeds(lines []string) []int {
var seeds []int
seedListString := strings.Split(lines[0], ": ")[1]
for _, seedString := range strings.Split(seedListString, " ") {
seedNumber, _ := strconv.Atoi(seedString)
seeds = append(seeds, seedNumber)
}
return seeds
}
func parseAlmanacMaps(lines []string) []alamanacMap {
almanacMaps := []alamanacMap{}
currentMap := alamanacMap{}
for _, line := range lines[2:] {
if line == "" {
almanacMaps = append(almanacMaps, currentMap)
currentMap = alamanacMap{}
continue
}
if strings.Contains(line, ":") {
currentMap.mapName = strings.Split(line, " ")[0]
continue
}
almanacMapRange := almanacMapRange{}
fmt.Sscanf(
line,
"%d %d %d",
&almanacMapRange.destinationRangeStart,
&almanacMapRange.sourceRangeStart,
&almanacMapRange.rangeLength,
)
currentMap.ranges = append(currentMap.ranges, almanacMapRange)
}
almanacMaps = append(almanacMaps, currentMap)
return almanacMaps
}
func applyAlmanacMap(seedStart int, seedRange int, almanacMap alamanacMap) ([]int, []int) {
newSeedStarts := []int{}
newSeedRanges := []int{}
for _, almanacMapRange := range almanacMap.ranges {
if seedStart >= almanacMapRange.sourceRangeStart &&
seedStart < almanacMapRange.sourceRangeStart+almanacMapRange.rangeLength {
difference := almanacMapRange.sourceRangeStart - almanacMapRange.destinationRangeStart
newSeedStart := seedStart - difference
newSeedStarts = append(newSeedStarts, newSeedStart)
// If the full range of seeds is not contained within the current map range, we need to split the range
if seedStart+seedRange > almanacMapRange.sourceRangeStart+almanacMapRange.rangeLength {
// Append the range of seeds that is contained within the current map range
newSeedRanges = append(
newSeedRanges,
almanacMapRange.sourceRangeStart+almanacMapRange.rangeLength-newSeedStart,
)
// Check what seeds are not contained within the current map range and map them recursively
unmappedSeedStart := almanacMapRange.sourceRangeStart + almanacMapRange.rangeLength
unmappedSeedRange := seedStart + seedRange - unmappedSeedStart
mappedSeeds, mappedSeedRanges := applyAlmanacMap(
unmappedSeedStart,
unmappedSeedRange,
almanacMap,
)
newSeedStarts = append(newSeedStarts, mappedSeeds...)
newSeedRanges = append(newSeedRanges, mappedSeedRanges...)
continue
}
newSeedRanges = append(newSeedRanges, seedRange)
}
}
if len(newSeedStarts) == 0 {
newSeedStarts = append(newSeedStarts, seedStart)
newSeedRanges = append(newSeedRanges, seedRange)
}
return newSeedStarts, newSeedRanges
}