Added Solution for 2021 day 09

This commit is contained in:
Burnus 2023-04-21 14:37:05 +02:00
parent b45d9b1393
commit 10fb4f2561
5 changed files with 317 additions and 0 deletions

View file

@ -0,0 +1,8 @@
[package]
name = "day09_smoke_basin"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -0,0 +1,91 @@
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?*
Your puzzle answer was `524`.
\--- 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?*
Your puzzle answer was `1235430`.
Both parts of this puzzle are complete! They provide two gold stars: \*\*
At this point, you should [return to your Advent calendar](/2021) and try another puzzle.
If you still want to see it, you can [get your puzzle input](9/input).

View file

@ -0,0 +1,113 @@
use core::fmt::Display;
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
ParseIntError(char),
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ParseIntError(c) => write!(f, "Unable to parse {c} into integer"),
}
}
}
struct Map {
heights: Vec<Vec<usize>>,
}
impl TryFrom<&str> for Map {
type Error = ParseError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Ok(Self {
heights: value.lines().map(|line| line.chars().map(|c| c.to_digit(10).ok_or(Self::Error::ParseIntError(c)).map(|i| i as usize)).collect::<Result<Vec<_>, _>>()).collect::<Result<Vec<_>, _>>()?,
})
}
}
impl Map {
fn neighbours(&self, (x, y): (usize, usize)) -> Vec<((usize, usize), usize)> {
[(1, 0), (0, 1), (2, 1), (1, 2)].iter().filter(|(dx, dy)| (1..=self.heights[0].len()).contains(&(x+dx)) && (1..=self.heights.len()).contains(&(y+dy))).map(|(dx, dy)| ((x+dx-1, y+dy-1), self.heights[y+dy-1][x+dx-1])).collect()
}
fn is_local_low_point(&self, (x, y): (usize, usize)) -> bool {
let this_height = self.heights[y][x];
self.neighbours((x, y)).iter().all(|(_coords, height)| height > &this_height)
}
fn get_local_low_points(&self) -> Vec<usize> {
self.heights.iter()
.enumerate()
.flat_map(|(y, row)| row.iter()
.enumerate()
.filter(|(x, _height)| self.is_local_low_point((*x, y)))
.map(|(_x, height)| *height)
.collect::<Vec<_>>())
.collect()
}
}
pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
let mut map = Map::try_from(input)?;
let first = map.get_local_low_points().iter().map(|height| height+1).sum();
let second = get_largest_basin(&mut map);
Ok((first, second))
}
fn get_largest_basin(map: &mut Map) -> usize {
let height = map.heights.len();
let width = map.heights[0].len();
let mut basins = Vec::new();
// While it's tempting to only iterate over the local lows from step 1, we cannot garranty that
// every basin contains a local low point (there may be multiple consecutive points forming a
// valley of equal height). Therefore we iterate over the entire array.
(0..height).for_each(|y| {
(0..width).for_each(|x| {
let mut this_basin = 0;
let mut open_set = vec![(x, y)];
while let Some((x, y)) = open_set.pop() {
if map.heights[y][x] == 9 {
continue;
}
this_basin += 1;
map.heights[y][x] = 9;
for neighbour in map.neighbours((x, y)) {
open_set.push(neighbour.0);
}
}
basins.push(this_basin);
});
});
basins.sort_by(|a, b| b.cmp(&a));
basins.iter().take(3).product()
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
fn read_file(name: &str) -> String {
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
}
#[test]
fn test_sample() {
let sample_input = read_file("tests/sample_input");
assert_eq!(run(&sample_input), Ok((15, 1134)));
}
#[test]
fn test_challenge() {
let challenge_input = read_file("tests/challenge_input");
assert_eq!(run(&challenge_input), Ok((524, 1235430)));
}
}

View file

@ -0,0 +1,100 @@
9987675345698765453987654321234589999899878923493212345678999998656782467898999899878301234578998787
9876543234789765322398743210123567898789767899986101239899789876543101567897898798763212355989987656
3987784014897654310987654331235679965697644998765232345997654989765212799956999679854343466799976545
2199875323998765421298776542346789434595433498754345456789543499876353489549876542975858977899876439
1012965439899896432359987667457896546789322349987656987898932445987454578932987621986767898943989598
2125976598798989943467898876589999858899910959898767898976101234598966689431298320987898999432399987
3234987987656579894578989987679998769999899898769879999965422345679298995420139434598999896543459875
4346799876545456789679877898789769878989798799656989899876563496799109989591298548999689789656598764
5956998765434345698989765679895456989678679678943496789988689989898997979989987657987565698787989543
6899898764321234567999876989954345696534598789432134679999799976987656765778998769766464989999865432
7987679653210155789999997899875456789323999899521012345899899765698943254667999898954353578999654321
9696598654323234589788998998986567898919894958933423456789999753459892123458998987893212467898765432
8543498765434545679567899987987679987898743147894934567898989432398789334767987876789101298989876543
7656789878545656789338989876598789986797654235679895678997878941987678975879896545698914345678987654
9868998989656877892129678965439899975498754346998796789986867932954569986798765434567895458989998765
8979987798787898921012567894321999874329985459876589899985457899873458987987654323469986567899869876
7899876549898959999923456789432398765909876567987678999875322987654567898998773212378997698998754987
6534997831999943987894567897543999899899987878998789789964201298765678919679654323456789799987632399
5424598942689899876789678987659899988788999989019895699865362349986989103498795434567899899996549989
4212349653498789765699989798798789877697898999999924789976457899798993212379986747698946999897998878
5334569878989678934998995679987678954545987899789935689987567987649898763467897858789235798789887867
6446878989876569976897893459876567893239876797689898789397679893234789654598998979999546999698785458
7557989199987457898956789998984348994124965323486789895498798789123569875989109989898969898598654345
8998994398796346899545699876543236789549876412345678979569987679023456989878992398767898767469643234
9999689987654235695434689987652125678956987954456789768979876568994568999867989987659999955398759345
7887578976543123489545679698983234789768998765677993457899765456789878997654878998767899843229898956
6543469998768245678956789529865445899879999896798912349998987347899989989653467899879998732019987897
7672398999875456989767895439876556789989989999899102356987798456789899878932356789989987643498976789
8954987899986567899878976546989667993498979978976212469996549567895798969991245699899998754987685698
9769876989987898901989997656898789101997768769895433498765439878934987656789346789788999869876564567
9898765778998979312397899767999893249876753656789656569976524989423976546789498997697986998765473456
3987654569789765434456976978999974756965432345678987678987734694319887635689989998456894219874321567
2198733477678978645797895989989865669876543766799998789599848789998765212678979999367975323985432378
3989821234568999756898934599878976798998754567898999897679959899899874323599867895459876434596543458
9876432347679549887969423498969987897989865698997899979898767998798765435679756899567987546987654567
9876543489789832998953210987658998996579878789876588965939989987659987546789645688979987657898785678
3987654579898721239998723976547899987467989999995477894321098765545698687895436577898998898999896789
2398766789989654359899644597656999876345697679654356965434197543434989798954323456987899939998987893
1239887894678965498788987698987999765234789598765467896545976532129879899996534567896789123976798912
0945998923567896997687898999298987653123696439876588987679876549098765945987965778945693239875459901
9896789434678999876575999899399199762064594321987678998789989698987654326599878989238789459954345899
6797898645789998767434598798989349872165689410198989769899898997898543212367989994345678998986254678
5789949756894987654323497687878959989278796521239797653998767876799654302456999965456899987432123689
4569439887893998799934598576967898995478897432345698992989545665698775212567899876697899876543234567
5678921998969899987899974475459997898567998945456789989878932124569854323498976989989965987654345678
6799990199656789876798863212349976987678999896897899879767893234698765434578965699878974598785458789
9899989989543298765987652101267895999799998789998998968456789345999879545679854598767943459987569893
3998979678932129894598543323458934889934987698999987654345895469876997656789765987659894567998678942
1987667569892099989679656445667895679899876597896596543256896567989998789899876798547689978999789531
9876553456789989878998767986898996798788995456789987752125789678998999897999987899534567899989898940
8765432345679878967999899597959789987576789347899876543234589789987899975689999987656789929876967891
8764321234698766556899995329345678987455678956789989684348678999876798764567898998769893212975456932
9863210123459654345688989910258789876323589969894398765457789998765679923459987869878999109864349894
9854525234598743234567979891345897995474567898989239878767899997654567895678996555989998919753239789
9765434545987655455679865789457896986567678967878946989878959876543456789789789434599987898954398679
9896565656898766767999954567978965497678989656567898998989245988652346799894698765679876767895976532
9987879768999879879878323489989654398789893432349899987690159899721278967923989876798965456987987699
8998989879988989998965412397898765219899762101234789996521998798754367899999878987987654347898998987
7659395989876897987654323456789898323998753242345678989439887699865456899989769999876543236789019986
8543214598765456798987654589896987536789894355456989879598754589876967999877658999997655345678998965
7654323679876578969999865678945698545678976566567898769987653479989898998766546898998786457799987654
8795498793997989657899976789234987657799987677678965657898794567998789987653234567899898568899998723
9989989932398996546789989890123498968989998788789654346789887679899678996442123458901987678999899812
9878879993989875237899999989254989979878999899898766869895998997676567894321015667892398789999798923
7767767989878943123978999878969978998967899922939878998953219876565456976534124578943469999988697654
6553459876767894234568986767898767987656789210125989987994101985432389997645234567894590129876598785
5432345985458995679799875456989659876545456991234899876789919996676569987656545678965989239988439986
4321359894346789789987654345678943965434345789546799765679898987787878998787656989879879998895321298
5430198765497899894298763234567899876521234899987987654598787999898989109898767899998967897654210129
6541679876989945999987654345678989987752345678999999766987656579999793212999878999987656789775323234
6432589989877899998998765476989978998843459789998939878996545468989654329989999998798787894989876545
7543458998965778987679976687898767898754678999987923989876432345678976498978989987659898943497987676
8654567987854567896563987798998656899865789019876894599987321238789098987967878998743989932346798888
9766779876543488997432398899987745679877892198765789998765450139989129876754568999974567895459999999
9877898765632356789543459921096434567988943989654567899986521234678998765323467899865679976598897912
9988987654521237989699567899987558978999659876543457899987634656899986544212456789877889987987656893
9999996543210357678987998998998667989431968997652346998998785667901997432101348995998994398996545789
8932987987631234589476789987689978999599878994321345997899996778929899546712467894239987469997434679
7891098876546349679345678965578899998989989989935459876979897889298778994324578943190296599989323567
6989129989865478993234567893456799987878998776896567965468789990199656989435678954989987989978934569
5678949999976569310123689932345689876569899565789778984345688999987645678945789769979999878767897698
4567898999987679453294594321017992985498765434698999993234567898765434899656899998768999765457898987
7698987898799789564989695532399891996309899323456789832125678919876325999797999887657987654346789876
8999876789654998679879989649989799876212987437899898761012348901985476789898998765431298743235689985
9899965689543249998765679998767678965429876556945987652125667899876787899979459963210139852123798954
8788754799932129879654587789656567896578987987899876543234799998989898998764349854321298764234567893
7656543458794298965443445678932456789789598998901997654345678997693939789943298765432359879876899952
6543252345679987654352237899751577899895459789212398897656889986542124599892109887545456989987896541
8432101489989999875210128932967698998901345699924569998767994987431023999789213998676569995699965430
7654312678999998996321239999878789767892396989895678989879993976545129897678954598789678934567976521
8976433589998767987542356789999891557789989978789789467998989897685398789569899989899789325679897432
9987544567899655698653468999987910345679878765678992345987878799896987667348798976949895434599789545
9999655778999543219766567899876621234598765454567891249876567689929876543237667895435976565987679656
8798789989988959309877678999765432545699654323479910134995456578912997632123456789523498878996598977
6549891299876898912988989789876547686987543212567891239984323469329876321014567898654569989985456799
1234932997764667893499995678987658798998654403459932398765012478998765432125678979866789699876345678
0356799876543456994567894567898967899019873212378993987654139989219876843336789565977896579843234589
1235789987532345789978943456899878978929764323456789398543248892101998765459895434598965498765445678
2356897698421234567899432346789989767899875435668891239654356789432789887567976323699654329876786789
3567896543210246788987541457892499848921986546879910129767568996545699998678988434789543210989897899

View file

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