From dbd84eaa2e7c28255b034f12af45b8776e35e571 Mon Sep 17 00:00:00 2001 From: Dylan Butler Date: Tue, 5 Dec 2023 21:28:40 +1100 Subject: [PATCH] 2023-05 --- 2023/05/01.go | 92 ++++++++++++++++++ 2023/05/02.go | 119 +++++++++++++++++++++++ 2023/05/input.txt | 237 ++++++++++++++++++++++++++++++++++++++++++++++ 2023/05/puzzle.md | 141 +++++++++++++++++++++++++++ 2023/05/test1.txt | 33 +++++++ 2023/05/test2.txt | 33 +++++++ template/01.go | 1 - 7 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 2023/05/01.go create mode 100644 2023/05/02.go create mode 100644 2023/05/input.txt create mode 100644 2023/05/puzzle.md create mode 100644 2023/05/test1.txt create mode 100644 2023/05/test2.txt diff --git a/2023/05/01.go b/2023/05/01.go new file mode 100644 index 0000000..b779c39 --- /dev/null +++ b/2023/05/01.go @@ -0,0 +1,92 @@ +package main + +import ( + "embed" + "fmt" + "strings" + + "github.com/dbut2/advent-of-code/pkg/sti" + "github.com/dbut2/advent-of-code/pkg/test" + "github.com/dbut2/advent-of-code/pkg/utils" +) + +//go:embed input.txt +var input string + +//go:embed test*.txt +var tests embed.FS + +func main() { + t := test.Register(tests, solve) + t.Expect(1, 35) + fmt.Println(solve(input)) +} + +func solve(input string) int { + s := utils.ParseInput(input) + + var seeds []int + var mappings []mapping + + currentMapping := mapping{} + for _, line := range s { + if line == "" { + continue + } + + if strings.Contains(line, "seeds: ") { + seedsString := strings.Split(line, "seeds: ") + seedList := strings.Split(seedsString[1], " ") + for _, seedItem := range seedList { + seeds = append(seeds, sti.Sti(seedItem)) + } + continue + } + + if strings.Contains(line, "-") { + if len(currentMapping) > 0 { + mappings = append(mappings, currentMapping) + } + currentMapping = mapping{} + continue + } + + values := strings.Split(line, " ") + + currentMapping = append(currentMapping, submapping{ + source: sti.Sti(values[1]), + size: sti.Sti(values[2]), + offset: sti.Sti(values[0]) - sti.Sti(values[1]), + }) + } + if len(currentMapping) > 0 { + mappings = append(mappings, currentMapping) + } + + lowest := -1 + for _, seed := range seeds { + val := seed + + for _, mapping := range mappings { + for _, submapping := range mapping { + if val >= submapping.source && val <= submapping.source+submapping.size { + val += submapping.offset + break + } + } + } + + if lowest == -1 { + lowest = val + } + lowest = min(lowest, val) + } + + return lowest +} + +type mapping []submapping + +type submapping struct { + source, size, offset int +} diff --git a/2023/05/02.go b/2023/05/02.go new file mode 100644 index 0000000..8ed7ddd --- /dev/null +++ b/2023/05/02.go @@ -0,0 +1,119 @@ +package main + +import ( + "embed" + "fmt" + "strings" + + "github.com/dbut2/advent-of-code/pkg/sti" + "github.com/dbut2/advent-of-code/pkg/test" + "github.com/dbut2/advent-of-code/pkg/utils" +) + +//go:embed input.txt +var input string + +//go:embed test*.txt +var tests embed.FS + +func main() { + t := test.Register(tests, solve) + t.Expect(2, 46) + fmt.Println(solve(input)) +} + +func solve(input string) int { + s := utils.ParseInput(input) + + var seedPairs [][2]int + var mappings []mapping + + currentMapping := mapping{} + for _, line := range s { + if line == "" { + continue + } + + if strings.Contains(line, "seeds: ") { + seedsString := strings.Split(line, "seeds: ") + seedList := strings.Split(seedsString[1], " ") + + for i := 0; i < len(seedList); i += 2 { + seedPairs = append(seedPairs, [2]int{sti.Sti(seedList[i]), sti.Sti(seedList[i]) + sti.Sti(seedList[i+1])}) + } + continue + } + + if strings.Contains(line, "-") { + if len(currentMapping) > 0 { + mappings = append(mappings, currentMapping) + } + currentMapping = mapping{} + continue + } + + values := strings.Split(line, " ") + + currentMapping = append(currentMapping, submapping{ + source: sti.Sti(values[1]), + size: sti.Sti(values[2]), + offset: sti.Sti(values[0]) - sti.Sti(values[1]), + }) + } + if len(currentMapping) > 0 { + mappings = append(mappings, currentMapping) + } + + lowest := -1 + + for _, pair := range seedPairs { + ranges := [][2]int{pair} + + for _, mapping := range mappings { + for _, submapping := range mapping { + ranges = splitRangesAt(ranges, submapping.source) + } + + for i := range ranges { + ranges[i][0] = mapping.convert(ranges[i][0]) + ranges[i][1] = mapping.convert(ranges[i][1]) + } + } + + for i := range ranges { + if lowest == -1 { + lowest = ranges[i][0] + } + + lowest = min(lowest, ranges[i][0]) + } + } + + return lowest +} + +type mapping []submapping + +type submapping struct { + source, size, offset int +} + +func (m mapping) convert(in int) int { + for _, c := range m { + if in >= c.source && in <= c.source+c.size { + return in + c.offset + } + } + return in +} + +func splitRangesAt(s [][2]int, n int) [][2]int { + for i, ss := range s { + if n > ss[0] && n <= ss[1] { + s[i][1] = n - 1 + s = append(s, [2]int{n, ss[1]}) + return s + } + } + return s +} diff --git a/2023/05/input.txt b/2023/05/input.txt new file mode 100644 index 0000000..41b77cb --- /dev/null +++ b/2023/05/input.txt @@ -0,0 +1,237 @@ +seeds: 1187290020 247767461 40283135 64738286 2044483296 66221787 1777809491 103070898 108732160 261552692 3810626561 257826205 3045614911 65672948 744199732 300163578 3438684365 82800966 2808575117 229295075 + +seed-to-soil map: +1716002126 3982609232 32819234 +527777042 1448723593 108905538 +3097613512 2185535945 24556299 +3351444381 4015428466 144436121 +3331711186 3196645623 19733195 +169931418 1078390710 353970858 +1621489177 1746859318 67938624 +1904740745 2514777285 180582308 +2435282992 2210092244 85514440 +1398165946 286288423 41146536 +523902276 1432361568 3874766 +1903021413 3980889900 1719332 +1689427801 2875575735 26574325 +2085323053 2092073852 27802380 +1244196171 922461291 37612770 +3834107486 3846963083 28702903 +636682580 327434959 595026332 +3207795548 2695359593 118500381 +3035897751 2813859974 61715761 +3326295929 3875665986 5415257 +3122169811 4209341559 85625737 +3954618410 1867878056 11806468 +3027897115 3881081243 8000636 +74621536 159718198 10213220 +4091795019 1879684524 56951870 +4148746889 1995330417 96743435 +84834756 0 85096662 +3800092500 2331115565 34014986 +1281808941 169931418 116357005 +4245490324 4159864587 49476972 +2609257929 3467510702 57294822 +2113125433 3524805524 322157559 +2520797432 1936636394 58694023 +3495880502 1814797942 53080114 +1748821360 2119876232 65659713 +0 85096662 74621536 +3548960616 3216378818 251131884 +2931281840 2418162010 96615275 +1439312482 960074061 118316649 +2674851505 2910448814 256430335 +2666552751 2902150060 8298754 +3966424878 1621489177 125370141 +1231708912 1436236334 12487259 +3862810389 3889081879 91808021 +2579491455 3166879149 29766474 +1867512532 2295606684 35508881 +1814481073 2365130551 53031459 + +soil-to-fertilizer map: +900001914 416463108 281254528 +0 126604924 281385177 +281385177 1157253669 618616737 +1885448579 1775870406 139515090 +3016033145 2662884952 103067725 +1189729449 1110523399 46730270 +2123796167 0 126604924 +2809716281 3293179505 206316864 +3394722305 3499496369 373018163 +2250401091 1915385496 17843034 +2387263517 3872514532 299008639 +1181256442 407990101 8473007 +2686272156 4171523171 123444125 +3767740468 2765952677 527226828 +1236459719 1933228530 335015595 +1571475314 697717636 313973265 +2024963669 1011690901 98832498 +3119100870 2387263517 275621435 + +fertilizer-to-water map: +2043262733 3156005317 240398158 +740161853 3396403475 396633652 +2283660891 728762031 158542508 +338820086 530011363 198750668 +2442203399 1391771783 889292891 +3734522375 237378927 58514752 +3331496290 988745698 403026085 +1136795505 2814613159 341392158 +1809145049 295893679 234117684 +537570754 2281064674 202591099 +1478187663 2483655773 330957386 +237378927 887304539 101441159 + +water-to-light map: +3659569782 1525449239 315716712 +3476299666 1083068766 183270116 +3231355346 2188139141 105510824 +4174005670 3640676221 26006855 +2033660875 1999740193 45748640 +4057070245 1972906150 26834043 +972390863 634517173 12741770 +2909470443 3992972439 35114066 +3371367762 3517719799 18082344 +1577969948 2765252679 71346084 +1355403194 769026051 222566754 +1025652593 3705699048 26412059 +3389450106 2756144754 7720673 +519325900 2956875516 263858379 +3176461571 2056589398 54893775 +1649316032 3732111107 254481047 +4005461865 3535802143 40507815 +868266049 3220733895 65108842 +2323504821 1300840474 47494425 +4045969680 2045488833 11100565 +4083904288 2939503515 17372001 +933374891 3666683076 39015972 +2944584509 3285842737 231877062 +2603233578 442821495 41827275 +3403912268 4028086505 49362804 +860498512 2763865427 1387252 +4200012525 347866724 94954771 +387585701 1841165951 131740199 +2435365509 2293649965 167868069 +2170885476 733737763 35288288 +2645060853 484648770 149868403 +1903797079 1509336552 16112687 +3453275072 2733120160 23024594 +2370999246 3576309958 64366263 +3975286494 2909328144 30175371 +2206173764 2615789103 117331057 +226584048 1348334899 161001653 +3397170779 226584048 6741489 +2079409515 991592805 91475961 +3336866170 1266338882 34501592 +4101276289 2836598763 72729381 +1919909766 2502037994 113751109 +1268924374 647258943 86478820 +861885764 3986592154 6380285 +783842544 2111483173 76655968 +1052064652 4077449309 216859722 +783184279 4294309031 658265 +985132633 2461518034 40519960 +2794929256 233325537 114541187 + +light-to-temperature map: +3539333023 2561430684 132087009 +3698501184 4084205096 109385247 +3378310404 4253495312 1341714 +3379652118 4281918178 4529732 +3384181850 2314593178 64260938 +2785407303 2874819838 586422865 +25112293 160761603 162822339 +770938901 1968882287 168925624 +2705922239 2697964303 79485064 +512617614 0 160761603 +3671420032 4254837026 27081152 +673379217 387568324 33575302 +706954519 323583942 63984382 +1047197914 1580976419 38110593 +0 1619087012 25112293 +2297003964 4193590343 8717958 +187934632 1644199305 324682982 +4277378082 2297003964 17589214 +4227273431 2511326033 50104651 +939864525 1133158202 107333389 +2692956243 4286447910 8519386 +3448442788 2777449367 90890235 +1085308507 1240491591 340484828 +1425793335 421143626 712014576 +3371830168 2868339602 6480236 +2701475629 2693517693 4446610 +2305721922 4202308301 51187011 +3807886431 2378854116 132471917 +3940358348 3797290013 286915083 +2356908933 3461242703 336047310 + +temperature-to-humidity map: +4269649447 2393649810 25317849 +2624622018 1500892381 293269560 +3784916401 3939293015 342497756 +2265977332 3395782296 159502803 +1831892433 2656443697 262271473 +3165592569 2418967659 50349192 +2917891578 2918715170 32249137 +3152416044 4281790771 13176525 +2425480135 3196640413 199141883 +0 541439970 311711929 +1823766565 1492766513 8125868 +990491492 84547230 456892740 +311711929 0 84547230 +2950140715 2469316851 187126846 +4127414157 2950964307 142235290 +396259159 853151899 594232333 +3215941761 3555285099 21604105 +2094163906 2206687901 171813426 +3703390493 2125161993 81525908 +3340986682 3576889204 362403811 +3137267561 2378501327 15148483 +3237545866 3093199597 103440816 +1492766513 1794161941 331000052 + +humidity-to-location map: +697523568 606382276 38912139 +3022503077 2608306075 46906919 +3230895262 2302415707 63420952 +736435707 183964832 131646187 +3507404317 3731540503 41469688 +1013393252 490470958 115911318 +270068585 0 183964832 +3316292469 3480652736 191111848 +3800980345 2893452190 286098783 +2373021543 3773010191 190266 +3548874005 3993865558 91972017 +0 645294415 270068585 +2373211809 4094117141 87252238 +2856512732 2695675634 165990345 +2460464047 4085837575 8279566 +619680743 351018435 72089891 +3069409996 2365836659 129699055 +3640846022 3813115875 53385677 +2729080766 2240595460 61820247 +1554011298 1459823647 179489523 +1884012518 2495535714 112770361 +2468743613 3363193697 35293527 +3199109051 2861665979 31786211 +454033417 1031019876 98284694 +1733500821 1302115255 150511697 +1431930368 3773200457 39915418 +691770634 930855093 5752934 +3694231699 3671764584 59775919 +1302115255 2655212994 40462640 +868081894 936608027 94411849 +4087079128 4181369379 113597917 +1471845786 3398487224 82165512 +997901159 915363000 15492093 +2504037140 2015551834 225043626 +3761204313 3866501552 39776032 +552318111 423108326 67362632 +2790901013 3906277584 65611719 +3294316214 3971889303 21976255 +962493743 315611019 35407416 +4200677045 3268903446 94290251 +3754007618 1452626952 7196695 +1996782879 1639313170 376238664 +1342577895 3179550973 89352473 diff --git a/2023/05/puzzle.md b/2023/05/puzzle.md new file mode 100644 index 0000000..4bb46f3 --- /dev/null +++ b/2023/05/puzzle.md @@ -0,0 +1,141 @@ +\--- 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](https://en.wikipedia.org/wiki/Sand_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](https://en.wikipedia.org/wiki/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 `282277027`. + +\--- 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 `11554135`. + +Both parts of this puzzle are complete! They provide two gold stars: \*\* + +At this point, you should [return to your Advent calendar](/2023) and try another puzzle. + +If you still want to see it, you can [get your puzzle input](5/input). + +You can also [Shareon [Twitter](https://twitter.com/intent/tweet?text=I%27ve+completed+%22If+You+Give+A+Seed+A+Fertilizer%22+%2D+Day+5+%2D+Advent+of+Code+2023&url=https%3A%2F%2Fadventofcode%2Ecom%2F2023%2Fday%2F5&related=ericwastl&hashtags=AdventOfCode) [Mastodon](javascript:void(0);)] this puzzle. \ No newline at end of file diff --git a/2023/05/test1.txt b/2023/05/test1.txt new file mode 100644 index 0000000..f756727 --- /dev/null +++ b/2023/05/test1.txt @@ -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 diff --git a/2023/05/test2.txt b/2023/05/test2.txt new file mode 100644 index 0000000..f756727 --- /dev/null +++ b/2023/05/test2.txt @@ -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 diff --git a/template/01.go b/template/01.go index 00454d4..d21b001 100644 --- a/template/01.go +++ b/template/01.go @@ -2,7 +2,6 @@ package main import ( "embed" - _ "embed" "fmt" "github.com/dbut2/advent-of-code/pkg/test"