From cf112533317a347f6b6f20a5fedf6c64f8ae1b1b Mon Sep 17 00:00:00 2001 From: Colin Sullivan Date: Thu, 7 Dec 2023 04:10:47 +0000 Subject: [PATCH 1/2] day 5 part 1 --- data/day5.txt | 254 +++++++++++++++++++++++++++++++++++++++ docs/docs/CLI.md | 37 ++++++ docs/docs/day5/part1.md | 1 + docs/mkdocs.yml | 2 + src/aoc/cli.py | 22 ++++ src/aoc/day5/__init__.py | 0 src/aoc/day5/part1.py | 156 ++++++++++++++++++++++++ tests/test_day5.py | 39 ++++++ 8 files changed, 511 insertions(+) create mode 100644 data/day5.txt create mode 100644 docs/docs/day5/part1.md create mode 100644 src/aoc/day5/__init__.py create mode 100644 src/aoc/day5/part1.py create mode 100644 tests/test_day5.py diff --git a/data/day5.txt b/data/day5.txt new file mode 100644 index 0000000..59516ed --- /dev/null +++ b/data/day5.txt @@ -0,0 +1,254 @@ +seeds: 1132132257 323430997 2043754183 4501055 2539071613 1059028389 1695770806 60470169 2220296232 251415938 1673679740 6063698 962820135 133182317 262615889 327780505 3602765034 194858721 2147281339 37466509 + +seed-to-soil map: +1280158874 0 45923291 +0 1431836695 234754481 +2476778759 365219074 73714061 +3997869725 4152785341 16553125 +3014496893 3731980396 420804945 +3435301838 2667516045 60128827 +2784964719 2727644872 187996890 +792043155 613341484 49447658 +1444573280 2476024240 74468580 +2728723659 3675739336 56241060 +2704677524 4236229588 24046135 +2360313001 1780050354 116465758 +1326082165 226504189 118491115 +3495430665 3630596320 3607732 +1519041860 662789142 56785021 +3973462947 3383860003 24406778 +1575826881 45923291 119425025 +1695251906 766775600 665061095 +2667516045 3323175190 6512477 +4240794960 3329687667 54172336 +720792676 344995304 20223770 +489053726 438933135 143852141 +741016446 746305099 20470501 +3499038397 4169338466 66891122 +761486947 582785276 30556208 +3565929519 3249598798 73576392 +659636803 165348316 61155873 +234754481 2221724995 254299245 +2674028522 4260275723 30649002 +841490813 1896516112 325208883 +632905867 719574163 26730936 +1166699696 1666591176 113459178 +2972961609 3634204052 41535284 +4195000071 3408266781 45794889 +4190957500 4290924725 4042571 +3639505911 2915641762 333957036 +4014422850 3454061670 176534650 + +soil-to-fertilizer map: +528009375 3804807330 65591757 +3608285775 3569685636 235121694 +432120564 3045118038 95888811 +3843407469 1792428879 363149111 +4206556580 2155577990 88410716 +3441777 3141006849 428678787 +1019419908 3870399087 424568209 +593601132 2619299262 425818776 +1443988117 3441777 1788987102 +3232975219 2243988706 375310556 + +fertilizer-to-water map: +3768646817 2541098841 42522952 +657445332 493998363 293094466 +3153469588 3947073749 287697992 +2513829777 3047249136 215146452 +968568929 29638292 96921246 +1600806946 1111339724 96961929 +3880726440 2687212715 52238929 +416544049 1090614661 20725063 +1749924539 4274983783 15782292 +1306572576 1208301653 21184719 +2134505230 4234771741 40212042 +1697768875 0 29638292 +3811169769 2617656044 69556671 +487527141 787092829 169918191 +3932965369 2583621793 34034251 +178562138 1471396125 237981911 +2728976229 3010972799 36276337 +2174717272 3262395588 176952386 +3035746039 1749924539 117723549 +2794475974 2764473831 241270065 +437269112 443740334 50258029 +2790274753 4290766075 4201221 +3441167580 3767315650 179758099 +3966999620 3439347974 327967676 +2351669658 2236446487 162160119 +1585319642 1229486372 15487304 +1327757295 186177987 257562347 +2765252566 2739451644 25022187 +950539798 1709378036 18029131 +1765706831 1867648088 368798399 +1199093816 1363917365 107478760 +3763417914 3005743896 5228903 +1065490175 957011020 133603641 +3620925679 2398606606 142492235 +59618449 1244973676 118943689 +0 126559538 59618449 + +water-to-light map: +2368177077 1928300684 68416280 +3459327457 4032125413 181740227 +2874128303 2996109939 93290692 +40167335 1203835270 50270286 +2984608918 3988581415 43543998 +1295445723 891961544 129160430 +232873619 72411133 344405432 +4002859459 4225073350 66563582 +3451555101 2874128303 4441992 +3957368975 2950619455 45490484 +4192270745 3148930063 6297777 +1638782153 2125726715 498901151 +3028152916 2912054150 38565305 +577279051 1504061698 367203335 +3418071246 2878570295 33483855 +3897839543 3089400631 59529432 +2967418995 3166056654 3449280 +3641067684 3835626234 152955181 +4147219041 3436688572 45051704 +2436593357 1021121974 182713296 +3066718221 3484273209 351353025 +2647866375 1254105556 189577037 +4198568522 3340289798 96398774 +2619306653 39188438 21015758 +2982075985 3481740276 2532933 +4069423041 3155227840 10828814 +2186332185 1443682593 52835141 +90437621 678875874 142435998 +980629741 2624627866 212815546 +2239167326 1996716964 129009751 +1424606153 571958210 106917664 +0 1871265033 40167335 +2980967789 4223965154 1108196 +1619041805 450217426 19740348 +1193445287 469957774 102000436 +944482386 426277008 23940418 +4080251855 3169505934 66967186 +1548392133 821311872 70649672 +1531523817 1911432368 16868316 +2970868275 4213865640 10099514 +3455997093 4291636932 3330364 +2137683304 416816565 9460443 +3794022865 3236473120 103816678 +2147143747 0 39188438 +2640322411 1496517734 7543964 +968422804 60204196 12206937 + +light-to-temperature map: +224631556 2579077346 68012835 +93390978 2647090181 93292258 +836334842 260175809 93895333 +3305235739 4175688657 119278639 +2495493200 354071142 67947352 +2563440552 648390650 214063090 +4184988573 4065709934 109978723 +930230175 2740382439 151863620 +2777503642 1813071562 114742417 +3424514378 3772814840 292895094 +1492090043 422018494 226372156 +3717409472 3176683751 126763710 +3273297 2243837725 90117681 +1216313119 2511603925 67473421 +4104753748 3096448926 80234825 +2392410003 1112358810 103083197 +759707869 2434976952 76626973 +2031212648 2333955406 101021546 +2132234194 0 260175809 +1718462199 1931087276 312750449 +186683236 1682505485 37948320 +1174711552 1070757243 41601567 +292644391 1215442007 467063478 +3844173182 3512234274 260580566 +1283786540 862453740 208303503 +3096448926 3303447461 208786813 +1082093795 1720453805 92617757 +0 1927813979 3273297 + +temperature-to-humidity map: +1908382071 0 48093237 +1668173777 369927146 108464980 +2454615458 3265918092 19222900 +2948843885 2383489773 582426713 +1291899323 304752282 65174864 +4051886972 3793288156 243080324 +2849120094 3285140992 99723791 +2415628816 3186987107 38986642 +724194709 716571124 379381363 +1103576072 2070505932 18664072 +3531270598 1602200086 102620550 +4020906946 3755760878 30980026 +1122240144 2285968817 97520956 +2779959793 1533039785 69160301 +1357074187 2089170004 196798813 +1823337263 624772153 85044808 +561911923 1433912547 99127238 +2538151277 1095952487 222368482 +1776638757 709816961 6754163 +2248869517 1776958859 59989455 +2760519759 48093237 3497277 +3770981692 4278303020 16664276 +3755760878 4263082206 15220814 +2497298857 263899862 40852420 +2473838358 1900103862 23460499 +234010997 51590514 212309348 +661039161 1836948314 63155548 +0 1923564361 87630970 +1219761100 1704820636 72138223 +87630970 478392126 146380027 +1956475308 3462247498 171643650 +3787645968 3786740904 6547252 +2764017036 2054563175 15942757 +2171486802 3384864783 77382715 +446320345 1318320969 115591578 +1783392920 3225973749 39944343 +2308858972 2965916486 106769844 +1553873000 3072686330 114300777 +3794193220 4036368480 226713726 +2128118958 2011195331 43367844 + +humidity-to-location map: +2944942064 3820503519 61983659 +3834803738 3234323053 106874653 +2156211251 3962463577 28956273 +483302901 3882487178 79976399 +2282996952 2161034243 46548053 +2629999410 1876993734 225283872 +3370099006 3129013552 105309501 +1029930529 620272722 135507476 +3572091970 2932598747 109287331 +3739626327 942443797 51739908 +3311342369 2102277606 58756637 +3941678391 399929037 136325691 +1245368468 58880743 172279414 +790057642 1189404679 239872887 +1498307968 3341197706 67668316 +273081010 616914814 3357908 +2501095485 2803694822 128903925 +3475408507 4198283833 96683463 +1860675375 3456652816 219039792 +245544342 2207582296 27536668 +3006925723 1666468371 210525363 +3791366235 3733939634 11933242 +1165438005 1502653815 79930463 +1691906495 231160157 168768880 +1590576804 994183705 101329691 +2079715167 2235118964 76496084 +276438918 3991419850 206863983 +563279300 2507766048 226778342 +2855283282 3408866022 47786794 +1565976284 2311615048 24600520 +3217451086 1095513396 93891283 +3803299477 1429277566 31504261 +4161888175 2757743175 45951647 +2903070076 1460781827 41871988 +3681379301 3675692608 58247026 +4207839822 3041886078 87127474 +2185167524 2734544390 23198785 +2329545005 2336215568 171550480 +4078004082 1582584278 83884093 +1417647882 536254728 80660086 +58880743 755780198 186663599 +2208366309 3745872876 74630643 diff --git a/docs/docs/CLI.md b/docs/docs/CLI.md index 44a703a..62113b3 100644 --- a/docs/docs/CLI.md +++ b/docs/docs/CLI.md @@ -21,6 +21,7 @@ $ aoc [OPTIONS] COMMAND [ARGS]... * `day2`: Command for running day2 stars * `day3`: Command for running day3 stars * `day4`: Command for running day4 stars +* `day5`: Command for running day5 stars * `debug-version-info`: Print debug information to terminal. ## `aoc day1` @@ -243,6 +244,42 @@ $ aoc day4 part2 [OPTIONS] [INPUT_PATH] * `--help`: Show this message and exit. +## `aoc day5` + +Command for running day5 stars + +**Usage**: + +```console +$ aoc day5 [OPTIONS] COMMAND [ARGS]... +``` + +**Options**: + +* `--help`: Show this message and exit. + +**Commands**: + +* `part1`: Calculate the nearest location for planting. + +### `aoc day5 part1` + +Calculate the nearest location for planting. + +**Usage**: + +```console +$ aoc day5 part1 [OPTIONS] [INPUT_PATH] +``` + +**Arguments**: + +* `[INPUT_PATH]`: Path to file containing the input [default: data/day5.txt] + +**Options**: + +* `--help`: Show this message and exit. + ## `aoc debug-version-info` Print debug information to terminal. diff --git a/docs/docs/day5/part1.md b/docs/docs/day5/part1.md new file mode 100644 index 0000000..db03327 --- /dev/null +++ b/docs/docs/day5/part1.md @@ -0,0 +1 @@ +## ::: aoc.day5.part1 diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f9be85c..843344a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -19,6 +19,8 @@ nav: - Day 4: - Part 1: day4/part1.md - Part 2: day4/part2.md + - Day 5: + - Part 1: day5/part1.md theme: diff --git a/src/aoc/cli.py b/src/aoc/cli.py index 1502a7a..e83094c 100644 --- a/src/aoc/cli.py +++ b/src/aoc/cli.py @@ -12,6 +12,7 @@ from aoc.day3.part2 import sum_gear_ratios from aoc.day4.part1 import card_points from aoc.day4.part2 import count_cards +from aoc.day5.part1 import nearest_location __version__ = version(__package__) @@ -221,3 +222,24 @@ def day4part2( cli.add_typer(day4app, name="day4") + +day5app = typer.Typer( + help="Command for running day5 stars", + rich_markup_mode="rich", +) + + +@day5app.command(name="part1") +def day5part1( + input_path: Path = typer.Argument( + Path("data/day5.txt"), help="Path to file containing the input" + ), +) -> None: + """Calculate the nearest location for planting.""" + with open(input_path) as infile: + input_text = infile.read() + total_sum = nearest_location(input_text) + print(f"The nearest location is: [bold red]{total_sum}[/bold red]") + + +cli.add_typer(day5app, name="day5") diff --git a/src/aoc/day5/__init__.py b/src/aoc/day5/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/aoc/day5/part1.py b/src/aoc/day5/part1.py new file mode 100644 index 0000000..d8b3302 --- /dev/null +++ b/src/aoc/day5/part1.py @@ -0,0 +1,156 @@ +""" +# 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? + +""" +from collections import defaultdict + + +def source_in_range(source: int, start: int, length: int) -> bool: + """Determine if the source is contained with in the range defined from start to start + length. + + Args: + source: search key + start: begin search range + length: number of successor values from start + + Returns: + if source is in the range + """ + return start <= source <= (start + length) + + +def nearest_location(input_text: str) -> int: + """Calculate the seed with the nearest location by following them through the mapped ranges to final locations. + + Args: + input_text: raw input + + Returns: + minimum location value + """ + groups = input_text.split("\n\n") + data: dict[str, dict[int, int]] = defaultdict(dict) + seeds = set(map(int, groups[0].split(": ")[1].split())) + prev_sources = seeds + for group in groups[1:]: + group_name, numbers = group.split(":\n") + new_prev_sources = set() + for line in numbers.split("\n"): + destination, source, length = map(int, line.strip().split()) + for prev_source in prev_sources: + if source_in_range(prev_source, source, length): + dest = destination + prev_source - source + data[group_name][prev_source] = dest + else: + dest = prev_source + new_prev_sources.add(dest) + prev_sources = new_prev_sources + + min_location = max(data["humidity-to-location map"].values()) + for seed in seeds: + dest = seed + for group_name in data: + dest = data[group_name].get(dest, dest) + if dest < min_location: + min_location = dest + return min_location diff --git a/tests/test_day5.py b/tests/test_day5.py new file mode 100644 index 0000000..f6c7ec2 --- /dev/null +++ b/tests/test_day5.py @@ -0,0 +1,39 @@ +from aoc.day5.part1 import nearest_location + +input_text = """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""" + + +def test_min_location() -> None: + assert nearest_location(input_text) == 35 From 3aeafbf8b383911a479f05b84f60555138c89527 Mon Sep 17 00:00:00 2001 From: Colin Sullivan Date: Thu, 7 Dec 2023 04:12:06 +0000 Subject: [PATCH 2/2] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 90cf227..763d49c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aoc" -version = "0.4.0" +version = "0.5.0" description = "Record of current and past attempts at Advent-of-Code in Python" authors = ["Colin Sullivan "] readme = "README.md"