2023 Day 5 Complete!

This commit is contained in:
Brian Buller 2023-12-05 11:23:48 -06:00
parent 38a74e36d9
commit 1c5f960426
5 changed files with 636 additions and 0 deletions

201
2023/day05/input Normal file
View File

@ -0,0 +1,201 @@
seeds: 2637529854 223394899 3007537707 503983167 307349251 197383535 3543757609 276648400 2296792159 141010855 116452725 5160533 2246652813 49767336 762696372 160455077 3960442213 105867001 1197133308 38546766
seed-to-soil map:
1024364543 1121869540 764570177
1788934720 0 30748436
710359306 576061773 314005237
1819683156 509305212 66756561
478556776 890067010 231802530
0 30748436 478556776
soil-to-fertilizer map:
3998185854 3762642503 103735883
2968507762 2068943953 132922295
1615660383 3128249668 130118355
730037950 2201866248 85080413
30504699 101283437 22743985
1963198232 3098529992 29719676
2445396241 816829001 206574911
4101921737 3258368023 13795434
1745778738 3272163457 98082636
184429295 124027422 42778761
815118363 1688321922 16510291
227208056 0 101283437
3101430057 730037950 86791051
2855369613 1073802717 8286129
2726882317 4266444706 28522590
2755404907 1647814534 40507388
1992917908 4002766747 184714231
0 307861200 20630293
3437715786 2286946661 488868406
2212191740 2910044568 188485424
1875478802 3756833622 5808881
1386084226 4200760960 31124145
4115717171 1704832213 179250125
2177632139 4231885105 34559601
968017015 3370246093 57414778
1957518504 1068122989 5679728
20630293 205631872 9874406
1248075951 2775815067 134229501
1417208371 1449362522 198452012
145603606 166806183 38825689
3926584192 1318303542 71601662
2651971152 3650305029 74911165
2863655742 1884082338 104852020
2400677164 1023403912 44719077
1025431793 3427660871 222644158
53248684 215506278 92354922
2795912295 1389905204 59457318
831628654 3866378386 136388361
1382305452 2065165179 3778774
1843861374 3725216194 31617428
3188221108 1082088846 236214696
1881287683 1988934358 76230821
3424435804 4187480978 13279982
fertilizer-to-water map:
52426778 0 42548209
2317094055 2628693938 80884528
4273469923 2317094055 21497373
3504443816 3801741356 19441920
1168510873 722677906 36277136
766143928 2147127897 113763545
2859981871 4203009036 91958260
3742911607 2903448576 530558316
2533492330 3494200839 307540517
1048443265 602610298 120067608
1606177181 2049845518 37728052
0 2087573570 24184027
2228508217 539688172 62922126
3523885736 4014822611 112866625
3636752361 3821183276 106159246
2204777013 515956968 23731204
163272748 80266080 177461896
340734644 1624436234 425409284
1568459310 42548209 37717871
3039420220 2338591428 290102510
1336392351 257727976 5651080
2397978583 3434006892 60193947
2951940131 3927342522 87480089
94974987 341413667 68297761
1750150773 263379056 78034611
1932038162 1351697383 272738851
1828185384 897499179 73313877
1563080665 758955042 5378645
1643905233 409711428 106245540
3329522730 2799034919 104413657
1901499261 2260891442 30538901
879907473 764333687 133165492
1342043431 1130660149 221037234
2458172530 4127689236 75319800
2841032847 2709578466 18949024
24184027 1102417398 28242751
1204788009 970813056 131604342
1013072965 2111757597 35370300
3433936387 2728527490 70507429
water-to-light map:
71899121 201997255 39056119
1870747295 791060221 18793056
1109877678 2647277659 20201672
496126127 1366401345 54786206
2289070096 3946384506 79288366
2872432379 3633289978 245210479
2566896529 1931266150 305535850
2094153218 1065408320 14844701
1747071839 1759996387 105111897
3528644588 1080253021 193678883
675287597 4169571318 125395978
1852183736 3256553708 6224195
611190115 1486911572 64097482
1972384294 809853277 55611058
4292231732 3217343431 613168
1498491937 2667479331 11999801
1356554237 502551806 141937700
110955240 241053374 38164682
800683575 2316420571 309194103
2368358462 2236802000 62837191
2523665094 3878500457 34541659
3488154933 3913042116 10582322
567693713 1443415170 43496402
2558206753 3247863932 8689776
4065356099 2990467798 226875633
3992305706 2625614674 21662985
4013968691 739672813 51387408
1330023335 1421187551 22227619
550912333 2299639191 16781380
1352250954 496126127 4303283
2027995352 1865108284 66157866
1889540351 644489506 82843943
3117642858 3262777903 370512075
3498737255 3217956599 29907333
2431195653 1273931904 92469441
1858407931 727333449 12339364
0 130098134 71899121
2170307311 2679479132 41006431
2211313742 4025672872 54996286
4292844900 500429410 2122396
149119922 0 130098134
1719479071 4141978550 27592768
3722323471 2720485563 269982235
2266310028 3923624438 22760068
2108997919 4080669158 61309392
1510491738 1551009054 208987333
1130079350 865464335 199943985
light-to-temperature map:
2246981140 2123929713 26608756
506825382 1211085022 100001399
2273589896 3259651351 49795378
606826781 48305627 403771586
2441004040 1311086421 255128583
2696132623 887597567 323487455
3131241320 452077213 69964335
1483012724 2119418493 4511220
4100438569 4209824659 85142637
2046786877 3309446729 95808859
1487523944 2344091207 205790126
3125128781 522041548 6112539
74735386 1566215004 432089996
2323385274 2937379483 117618766
46634343 2549881333 28101043
1215251469 1998305000 118258255
3201205655 0 1671284
3202876939 2150538469 193552738
1010598367 3054998249 204653102
3019620078 2577982376 105508703
2142595736 2832994079 104385404
1333509724 2683491079 149503000
4185581206 4100438569 109386090
1693314070 534124760 353472807
3396429677 528154087 5970673
0 1671284 46634343
3402400350 2116563255 2855238
temperature-to-humidity map:
3585785215 3115915735 709182081
1595400550 915086594 131894638
3115915735 3825097816 469869480
257043810 1628903919 98391269
355435079 1106926810 521977109
877412188 0 717988362
59945578 717988362 197098232
0 1046981232 59945578
humidity-to-location map:
2826523858 2649651094 205250361
2028276378 1553868404 798247480
225543770 4100328990 5722049
595208874 2352115884 297535210
3031774219 2854901455 205611797
1267642800 3435411968 22064409
138173954 4119345931 87369816
231265819 49632084 363943055
1877617809 1403209835 150658569
0 413575139 138173954
3237386016 3457476377 642852613
892744084 3060513252 374898716
3893533521 551749093 313182226
1339339293 864931319 538278516
1289707209 0 49632084
3880238629 4106051039 13294892

218
2023/day05/main.go Normal file
View File

@ -0,0 +1,218 @@
package main
import (
"fmt"
"math"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
fmt.Println()
part2(inp)
}
func part1(input []string) {
a := BuildAlmanac(input)
fmt.Println("# Part 1")
fmt.Println(h.SliceMin(a.findAllSeedLocations()))
}
func part2(input []string) {
a := BuildAlmanac(input)
fmt.Println("# Part 2")
fmt.Println(a.findLowestFromPairs())
}
type Seed struct {
start, length int
}
type Almanac struct {
seeds []int
seedRanges []Seed
mappings map[string]*RangeMap
rangeMap *RangeMap
locRangeMap *RangeMap
mapOrder []string
}
func BuildAlmanac(input []string) *Almanac {
a := Almanac{
mappings: make(map[string]*RangeMap),
mapOrder: []string{
"seed-to-soil",
"soil-to-fertilizer",
"fertilizer-to-water",
"water-to-light",
"light-to-temperature",
"temperature-to-humidity",
"humidity-to-location",
},
}
for _, v := range strings.Fields(input[0])[1:] {
a.seeds = append(a.seeds, h.Atoi(v))
}
i := 2
for ; i < len(input); i++ {
wrkMap, wrkI := parseMapAt(input[i:])
a.mappings[wrkMap.name] = wrkMap
i = i + wrkI
}
for i, m := range a.mapOrder {
if i == 0 {
a.rangeMap = a.mappings[m]
}
if i < len(a.mapOrder)-1 {
a.mappings[m].next = a.mappings[a.mapOrder[i+1]]
a.mappings[a.mapOrder[i+1]].prev = a.mappings[m]
} else {
a.mappings[m].prev = a.mappings[a.mapOrder[i-1]]
a.locRangeMap = a.mappings[m]
}
}
a.getSeedRanges()
return &a
}
func (a *Almanac) getSeedRanges() {
for i := 0; i < len(a.seeds); i++ {
seed := a.seeds[i]
i++
num := a.seeds[i]
a.seedRanges = append(a.seedRanges, Seed{
start: seed,
length: num,
})
}
}
func (a *Almanac) findAllSeedLocations() []int {
var res []int
for i := range a.seeds {
res = append(res, a.rangeMap.find(a.seeds[i]))
}
return res
}
func (a *Almanac) findLowestFromPairs() int {
for loc := 0; loc < math.MaxInt; loc++ {
seed := a.locRangeMap.findDest(loc)
for _, s := range a.seedRanges {
if seed >= s.start && seed <= s.start+s.length-1 {
return loc
}
}
}
return h.MIN_INT
}
func (a Almanac) String() string {
res := fmt.Sprintln("Seeds:", a.seeds)
for i := range a.mappings {
res = fmt.Sprintf("%s\n%s\n", res, a.mappings[i])
}
return res
}
type RangeMap struct {
name string
next *RangeMap
prev *RangeMap
associations []Association
hereToLoc map[int]int
lastFind int
}
func parseMapAt(input []string) (*RangeMap, int) {
name := strings.Fields(input[0])[0]
res := &RangeMap{
name: name,
associations: []Association{},
hereToLoc: make(map[int]int),
}
i := 1
for ; i < len(input); i++ {
if input[i] == "" {
break
}
pts := strings.Fields(input[i])
assoc := Association{
startSource: h.Atoi(pts[1]),
startDest: h.Atoi(pts[0]),
assocRange: h.Atoi(pts[2]),
}
assoc.diff = assoc.startDest - assoc.startSource
res.associations = append(res.associations, assoc)
}
return res, i
}
func (r *RangeMap) find(source int) int {
if v, ok := r.hereToLoc[source]; ok {
return v
}
next := source
for _, a := range r.associations {
if a.has(source) {
next = a.find(source)
}
}
if r.next == nil {
return next
} else {
ret := r.next.find(next)
r.hereToLoc[source] = ret
return ret
}
}
func (r *RangeMap) findDest(dest int) int {
prev := dest
for i := len(r.associations) - 1; i >= 0; i-- {
a := r.associations[i]
if a.hasDest(dest) {
prev = a.findSource(dest)
}
}
if r.prev == nil {
return prev
} else {
return r.prev.findDest(prev)
}
}
func (r *RangeMap) setLastFindResult(to int) {
r.hereToLoc[r.lastFind] = to
}
func (r RangeMap) String() string {
res := fmt.Sprintf("%s map:", r.name)
for _, v := range r.associations {
res = fmt.Sprintf("%s\n%s", res, v)
}
return res
}
type Association struct {
startSource int
startDest int
assocRange int
diff int
}
func (a *Association) has(source int) bool {
return source >= a.startSource && source < a.startSource+a.assocRange
}
func (a *Association) find(source int) int {
return source + a.diff
}
func (a *Association) hasDest(dest int) bool {
return dest >= a.startDest && dest < a.startDest+a.assocRange
}
func (a *Association) findSource(dest int) int {
return dest - a.diff
}
func (a Association) String() string {
return fmt.Sprintf("%d %d %d", a.startSource, a.startDest, a.assocRange)
}

172
2023/day05/problem Normal file
View File

@ -0,0 +1,172 @@
Advent of Code
br0xen (AoC++) 10*
--- Day 5: If You Give A Seed A Fertilizer ---
You take the boat and find the gardener right where you were told he would be: managing a giant "garden" that looks more to you like a farm.
"A water source? Island Island is the water source!" You point out that Snow Island isn't receiving any water.
"Oh, we had to stop the water because we ran out of sand to filter it with! Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand
soon; we only turned off the water a few days... weeks... oh no." His face sinks into a look of horrified realization.
"I've been so busy making sure everyone here has food that I completely forgot to check why we stopped getting more sand! There's a ferry leaving soon that
is headed over in that direction - it's much faster than your boat. Could you please go check it out?"
You barely have time to agree to this request when he brings up another. "While you wait for the ferry, maybe you can help us with our food production
problem. The latest Island Island Almanac just arrived and we're having trouble making sense of it."
The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what type of soil to use with each kind of seed, what type of
fertilizer to use with each kind of soil, what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil, fertilizer and so on
is identified with a number, but numbers are reused by each category - that is, soil 123 and fertilizer 123 aren't necessarily related to each other.
For example:
seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4
The almanac starts by listing which seeds need to be planted: seeds 79, 14, 55, and 13.
The rest of the almanac contains a list of maps which describe how to convert numbers from a source category into numbers in a destination category. That
is, the section that starts with seed-to-soil map: describes how to convert a seed number (the source) to a soil number (the destination). This lets the
gardener and his team know which soil to use with which seeds, which water to use with which fertilizer, and so on.
Rather than list every source number and its corresponding destination number one by one, the maps describe entire ranges of numbers that can be converted.
Each line within a map contains three numbers: the destination range start, the source range start, and the range length.
Consider again the example seed-to-soil map:
50 98 2
52 50 48
The first line has a destination range start of 50, a source range start of 98, and a range length of 2. This line means that the source range starts at 98
and contains two values: 98 and 99. The destination range is the same length, but it starts at 50, so its two values are 50 and 51. With this information,
you know that seed number 98 corresponds to soil number 50 and that seed number 99 corresponds to soil number 51.
The second line means that the source range starts at 50 and contains 48 values: 50, 51, ..., 96, 97. This corresponds to a destination range starting at
52 and also containing 48 values: 52, 53, ..., 98, 99. So, seed number 53 corresponds to soil number 55.
Any source numbers that aren't mapped correspond to the same destination number. So, seed number 10 corresponds to soil number 10.
So, the entire list of seed numbers and their corresponding soil numbers looks like this:
seed soil
0 0
1 1
... ...
48 48
49 49
50 52
51 53
... ...
96 98
97 99
98 50
99 51
With this map, you can look up the soil number required for each initial seed number:
 Seed number 79 corresponds to soil number 81.
 Seed number 14 corresponds to soil number 14.
 Seed number 55 corresponds to soil number 57.
 Seed number 13 corresponds to soil number 13.
The gardener and his team want to get started as soon as possible, so they'd like to know the closest location that needs a seed. Using these maps, find
the lowest location number that corresponds to any of the initial seeds. To do this, you'll need to convert each seed number through other categories until
you can find its corresponding location number. In this example, the corresponding types are:
 Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82.
 Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43.
 Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86.
 Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35.
So, the lowest location number in this example is 35.
What is the lowest location number that corresponds to any of the initial seed numbers?
Your puzzle answer was 323142486.
--- Part Two ---
Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it looks like the seeds: line actually describes ranges of
seed numbers.
The values on the initial seeds: line come in pairs. Within each pair, the first value is the start of the range and the second value is the length of the
range. So, in the first line of the example above:
seeds: 79 14 55 13
This line describes two ranges of seed numbers to be planted in the garden. The first range starts with seed number 79 and contains 14 values: 79, 80, ...,
91, 92. The second range starts with seed number 55 and contains 13 values: 55, 56, ..., 66, 67.
Now, rather than considering four seed numbers, you need to consider a total of 27 seed numbers.
In the above example, the lowest location number can be obtained from seed number 82, which corresponds to soil 84, fertilizer 84, water 84, light 77,
temperature 45, humidity 46, and location 46. So, the lowest location number is 46.
Consider all of the initial seed numbers listed in the ranges on the first line of the almanac. What is the lowest location number that corresponds to any
of the initial seed numbers?
Your puzzle answer was 79874951.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, you should return to your Advent calendar and try another puzzle.
If you still want to see it, you can get your puzzle input.
You can also [Shareon Twitter Mastodon] this puzzle.
References
Visible links
. https://adventofcode.com/
. https://adventofcode.com/2023/about
. https://adventofcode.com/2023/events
. https://teespring.com/stores/advent-of-code
. https://adventofcode.com/2023/settings
. https://adventofcode.com/2023/auth/logout
. Advent of Code Supporter
https://adventofcode.com/2023/support
. https://adventofcode.com/2023
. https://adventofcode.com/2023
. https://adventofcode.com/2023/support
. https://adventofcode.com/2023/sponsors
. https://adventofcode.com/2023/leaderboard
. https://adventofcode.com/2023/stats
. https://adventofcode.com/2023/sponsors
. https://en.wikipedia.org/wiki/Sand_filter
. https://en.wikipedia.org/wiki/Almanac
. https://adventofcode.com/2023
. https://adventofcode.com/2023/day/5/input

33
2023/day05/testinput Normal file
View File

@ -0,0 +1,33 @@
seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4

View File

@ -389,6 +389,18 @@ func IsPrime(value int) bool {
return value > 1 return value > 1
} }
func SliceMin(sl []int) int {
switch len(sl) {
case 0:
return MIN_INT
case 1:
return sl[0]
case 2:
return Min(sl[0], sl[1])
default:
return Min(sl[0], sl[1], sl[2:]...)
}
}
func Min(v1, v2 int, vrest ...int) int { func Min(v1, v2 int, vrest ...int) int {
min := v2 min := v2
if v1 < v2 { if v1 < v2 {