2021 Day 09

This commit is contained in:
Akumatic 2021-12-09 14:30:48 +01:00
parent 4f053d51d0
commit 51e358f06a
7 changed files with 251 additions and 1 deletions

71
2021/09/README.md Normal file
View File

@ -0,0 +1,71 @@
# 2021 Day 09: Smoke Basin
Copyright (c) Eric Wastl
#### [Direct Link](https://adventofcode.com/2021/day/09)
These caves seem to be [lava tubes](https://en.wikipedia.org/wiki/Lava_tube). Parts are even still volcanically active; small hydrothermal vents release smoke into the caves that slowly settles like rain.
If you can model how the smoke flows through the caves, you might be able to avoid it and be that much safer. The submarine generates a heightmap of the floor of the nearby caves for you (your puzzle input).
Smoke flows to the lowest point of the area it's in. For example, consider the following heightmap:
```
2199943210
3987894921
9856789892
8767896789
9899965678
```
Each number corresponds to the height of a particular location, where `9` is the highest and `0` is the lowest a location can be.
Your first goal is to find the **low points** - the locations that are lower than any of its adjacent locations. Most locations have four adjacent locations (up, down, left, and right); locations on the edge or corner of the map have three or two adjacent locations, respectively. (Diagonal locations do not count as adjacent.)
In the above example, there are **four** low points, all highlighted: two are in the first row (a `1` and a `0`), one is in the third row (a `5`), and one is in the bottom row (also a `5`). All other locations on the heightmap have some lower adjacent location, and so are not low points.
The **risk level** of a low point is **1 plus its height**. In the above example, the risk levels of the low points are `2`, `1`, `6`, and `6`. The sum of the risk levels of all low points in the heightmap is therefore **`15`**.
Find all of the low points on your heightmap. **What is the sum of the risk levels of all low points on your heightmap?**
--- Part Two ---
Next, you need to find the largest basins so you know what areas are most important to avoid.
A **basin** is all locations that eventually flow downward to a single low point. Therefore, every low point has a basin, although some basins are very small. Locations of height `9` do not count as being in any basin, and all other locations will always be part of exactly one basin.
The **size** of a basin is the number of locations within the basin, including the low point. The example above has four basins.
The top-left basin, size `3`:
```
2199943210
3987894921
9856789892
8767896789
9899965678
```
The top-right basin, size `9`:
```
2199943210
3987894921
9856789892
8767896789
9899965678
```
The middle basin, size `14`:
```
2199943210
3987894921
9856789892
8767896789
9899965678
```
The bottom-right basin, size `9`:
```
2199943210
3987894921
9856789892
8767896789
9899965678
```
Find the three largest basins and multiply their sizes together. In the above example, this is `9 * 14 * 9 = 1134`.
**What do you get if you multiply together the sizes of the three largest basins?**

58
2021/09/code.py Normal file
View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2021 Akumatic
#
# https://adventofcode.com/2021/day/09
def read_file(filename: str = "input.txt") -> tuple:
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
lines = [line for line in f.read().strip().split("\n")]
max_x = len(lines[0])
max_y = len(lines)
numbers = list()
for line in lines:
numbers += [int(x) for x in line]
return (max_x, max_y, numbers)
def get_neighbors(idx: int, max_x: int, max_y: int) -> list:
neighbors = list()
if idx >= max_x:
neighbors.append(idx - max_x)
if idx < (max_x * max_y - max_x):
neighbors.append(idx + max_x)
if idx % max_x != 0:
neighbors.append(idx - 1)
if idx % max_x != (max_x - 1):
neighbors.append(idx + 1)
return neighbors
def get_low_points(max_x, max_y, grid) -> list:
low_points = []
for i in range(len(grid)):
if all(grid[n] > grid[i] for n in get_neighbors(i, max_x, max_y)):
low_points.append(i)
return low_points
def expand(point, max_x, max_y, grid) -> set:
result = set()
l = {point}
while len(l) != 0:
p = l.pop()
result.add(p)
neighbors = {n for n in get_neighbors(p, max_x, max_y) if grid[n] != 9 and n not in result}
l = l.union(neighbors)
return result
def part1(max_x, max_y, grid) -> int:
low_points = get_low_points(max_x, max_y, grid)
return sum([grid[point] for point in low_points]) + len(low_points)
def part2(max_x, max_y, grid) -> int:
low_points = get_low_points(max_x, max_y, grid)
basin_sizes = [len(expand(point, max_x, max_y, grid)) for point in low_points]
basin_sizes.sort(reverse=True)
return basin_sizes[0] * basin_sizes[1] * basin_sizes[2]
if __name__ == "__main__":
vals = read_file()
print(f"Part 1: {part1(*vals)}")
print(f"Part 2: {part2(*vals)}")

100
2021/09/input.txt Normal file
View File

@ -0,0 +1,100 @@
2165679878998998656789210124569321954398786566799434678987678943987789543249654323496545436767898789
1034598769987897545678921235698949895987676445978926799876567899876678992198966212987432325456789678
2123987659866789756789654396987898789998543234567897989665476999865567889987654109976521012378994567
3299878543455699967899876989876765678987632125678998976562345698754378978998543298765432123499765678
4989865432324589878966989879985434569998545234569769987421976789653234567899955349896743276589876789
9876954321013678989545698767894325678987654345678956798599897898732145678989876456987654387678998891
8765985432124589995433989857895436799399795456789545459988789999546234589376987868998765678989219910
9879876543435699896512976546789945892198989767998932399875678987657355893245698979899896789698909899
2989988998747898789329865437897896789987678998967890989654589998778456789356789989754987896567998778
1098799987656789678998764323456789899876567899456999878963678999976567895467997897643498923458987668
2987632198789994589019973212367899998765456796347899767894567898989678976579656789732399212349876545
9876544999894123479929894343478989899954369965456987656789678967999799987689545698941987301298787636
8997659898943234567898765854589876789865238896769876547678989459898989998795434567899876312987654323
7898898767898765978929976765678945699832126789898765634567892398767678999896523458998765453498765678
6639986656789879899412987876789436798743235699999854323456789987654567896987212967899876589999876789
5429875345678998789323498987894323987654345678998743212369899996543498935698309898965989679878987891
6598765239889765678934679998921012398767656789987654323498998987654599324569498789654398798765498990
7987654378997654349895789989632123459878767999998785454567897998976678912978987698975459899854349789
8999876567898765456789999876543434569989979998999897565878966789988789439899999567896599989964235689
9998987679999876567899889989656545678996599987896999776989345678999899998789878456797989876543145678
9867898789899987898998778298767876789323459876745678989793216789899999867698765345989878985432014567
8756789996798998919987652109878989895414599765634569898672101236789987756549866239876767897643623478
5345678945987899901998943212989291954323989654523498789543234345678996543239654349765656789876534678
3234569129896987899879894523694390965439878943412987678954345689989989921098765698754545699998645789
4345878998765456798967779634569989876549969892109876589765476797899979899999876798643234589329756899
5676989987654345987759568965678977989698756789219987678976568945988869787894987987632123679998767998
8787899998763236796543467897789765398797645894398998989989679439876755656943299876543234567899878987
9898999879878345987622356789899879239987434789997879997898789598965634345892123987658545678979989876
7979998767989659876210145899978998949876325679886767896569898987654321234789014698987676789569898765
6567989654399998765431234998767987898765434598775756795456987898943210125679195989998987893498789654
4379878943239899876542347897654365699896556987654345689669876789994323234698989877899298912345678923
5498767892198789997659456789653234789987769876543234568979765878985467345997876766789129101234589214
6987656789297656989798967896543125898998998765432145678998654569876575459876985455678998212345678925
9876543899989549876987898987654014567999349654321035567896543467987986578965432324569987654476899434
3987912999878939885676799998954323699891298767632123459987932356798997989874321013478998785677898765
2399899878969998764365698999895434988789349876543234568999891238999898999985433144567899996789999876
1498789965458987653234567998789569875678956989854347678999789999998789999876543234878998987899899987
9987678994367998542123456789678979964569897898767898789988678789989678987987654345689987698998769898
8976569989239876521012345694589999873456789979878939899876545698976567896598765456899876569987656789
7665409879398765432125467893478987654589894567989323998787434567895457897459876567989765432398545899
6543219768999898743234567932367898765679923459891019987654323678912345978367998788978954321297656789
7654998957889987654565678943456789876789012398742198798776519799101256965459899899567895432398767898
8769897545678998767676789658967899989892123987653987679887698989912367896598789923456987563499898967
9899776534567899879789898767898978999943434598779876545998987679894567897987679646567898654989989656
8987654323479943989892999898999767899854545679897997634569876568789678999996598767678999769878978987
7598765454567892399921099989998656989769696789976598521698965457668999998889459878989998998767867998
6439976767878901998432989878987545678998989899998965430987674343456889987764367989299987899654358999
5321987988989919876549876567965434569987978998999876549876543212345678976543234590129876789543269789
4210198999797899989856998457896323459876767897989987856987652101234589987654125799298765789654345678
5323239789656789998769996567895454598765452346678999879876543212345892399775234598987654578975458989
6434345678945678999998987678987765997654301234569986989987654523456791498965345987694323459876767899
7546456799536569999877898789899899876543212365678965191298765789579890987896496976543213678989878989
7658567894423456985456789899764932989654323989789763239349878897689999876989989897954323489998989678
8769989943212569876578891998943210998765434599897654498999989998799998765679876789765434567897896567
9878999654301459988989990987894329879876565678999765597889993239899899654598765678986965698986543456
4989678943212398599998789876789498765987776789789897986778932101956789543219876789497876789995432345
3294567894343987456987698765679987654598887895678989765567893222345997654348989894398987899984321234
2123456789469876369876569654993298765789998924569878654456794533469898765656799989299798999875210123
1012687996598765298765498765894999876896549012698765433345679944598789876797899878987699998764323234
2144567897998654349874329876789899987987932123987654321256587895987678989898998767896587899875434765
3234588989899969498965214987896789998999893234598763210123456789876567899979987656789476567996999876
6545679876789898987654323498965678999998789456987654343234587895985456789567898967894353459989789989
7959798765865767898885554569654567899987678967898765454345689924594368893456999989943212398765678991
9898987874343456789876768678965678999876599978979876565456798765985457894577894598959101499754567892
6767896543212345678987979789876989987765487899568997876569899879876567895678923987998912989663458993
5456789652101256789698989892989898976521256789467898987678932989987678976989219896787899876562545789
4345789863218789896569992901299787895432349894345989998899543891298889987894398785676989765421234599
1235698754523698999678901292987676789765458943234567899978954789989999998995987654565678954310123459
2376789765434597898989992989876545678976567894345979998767895679876789879789898543454789765471266867
5488999878545986797899989876743434567899878987659898789856789798765678965698765432123499876562345678
6789578987659875456789878965432123498967989998769765678943656987654567893987654321012987989673456989
7892459898767954348898767896551012599459898999879874389432349897543456892198985432129896591989567896
8901598789898965467897657897662156789349767899989543278921298765432346789019876543298789432399998925
9212987653919876568998745698787345690198956789998784067890399764321235678923997854987678943989899014
4323496542109997679459956789876556789987546990987665156789987654310124789434598969876567899878789123
5654987673998698789349897990987697896543239891297543245678998765421249896595999198765434568965678934
6785698789876549893298789321298789989432129789987654376789879878432556987989891098764323487894567895
7896789898765434932197698934989896878941098691098765989898765986543477899876789199765412345993456789
8987894929876545693296567899878965767892986589129876789997654397676589998975678987654325896789567895
9199943212987676789985456789769874656789875478998998897986543298787699997754567898765434789899678934
1098956323498987899876567898956212345678976567896569976987672109898789876543456789878965678998989023
3987895454569999923987679967932101234589989678975456954398943212989899998754587892989878789987892134
9876789565678989219898989456893212345678998789986347895239654323578998929995678990194989899856789645
8765678978789678999789494345789924459789689899997468954398765434567897939876789789293299976745678957
7654589899896567987654323234567895678993594909876579765459898545678986898987897678989198765534567898
6543456799965456796543210125678998789301983212987989876589987656789765767998934569879989754323568999
7955677989656345987876521436789219893219976323499298987678998769897654459899123699769876545213467899
9876789878943245698987434545678999999398765454932127898789569899998943298767234987656987432102456789
9987898967892134589998545656989789998999986579843456999893457989999892129654349876549876543212345699
8799987655789023478987678987894599987891098798767897899912345679898789239765467999732987654325456789
7698765434568934567898789898923989876789199899899929999101234598767678949876878987621298995434567992
9569854323477895678909898769019874385878987956998919898919345987856567959989989099560129876545679543
5498765412346789789212999652198763234569876545987898767898959876543459898998992198432234987987899954
4329876101258999899854998943989753123778985439876789858967899987654598776787893987543456798998969895
5210987612567899998769887899876541014569896598765678969458978998996987654456789598654567899329457789
4329896523456789999898796598765432123456789699854569993234567899987998962367995459785678965412345678
7439765434567899899987687439876563234567899987653456889135698967899876543467892349876789879523456989
6549876569678998789876543312997654345678939798542345678956789456965987754578943656987897987634567891
9656987678989498642989932101239767456789329654321234589767892367894398967989764767898956798765678932
8767898989992349543498756322349878569895498765642355678998943456789239878998765678999547999896799653

2
2021/09/solution.txt Normal file
View File

@ -0,0 +1,2 @@
Part 1: 504
Part 2: 1558722

14
2021/09/test_code.py Normal file
View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2021 Akumatic
from code import part1, part2, read_file
def test():
vals = read_file("test_input.txt")
assert part1(*vals) == 15
print("Passed Part 1")
assert part2(*vals) == 1134
print("Passed Part 2")
if __name__ == "__main__":
test()

5
2021/09/test_input.txt Normal file
View File

@ -0,0 +1,5 @@
2199943210
3987894921
9856789892
8767896789
9899965678

View File

@ -23,7 +23,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
| 06 | :white_check_mark: | :white_check_mark: | [Solution](06/code.py) | [Day 06](https://adventofcode.com/2021/day/6) |
| 07 | :white_check_mark: | :white_check_mark: | [Solution](07/code.py) | [Day 07](https://adventofcode.com/2021/day/7) |
| 08 | :white_check_mark: | :white_check_mark: | [Solution](08/code.py) | [Day 08](https://adventofcode.com/2021/day/8) |
| 09 | | | | |
| 09 | :white_check_mark: | :white_check_mark: | [Solution](09/code.py) | [Day 09](https://adventofcode.com/2021/day/9) |
| 10 | | | | |
| 11 | | | | |
| 12 | | | | |