From 5b973ddf86a195ee118f4425f47c00c0059b72bb Mon Sep 17 00:00:00 2001 From: Alfred Melch Date: Sun, 9 Jan 2022 12:49:18 +0100 Subject: [PATCH] Solve 2021/09 --- 2021/day09/Cargo.lock | 7 ++ 2021/day09/Cargo.toml | 8 ++ 2021/day09/README.md | 46 ++++++++++ 2021/day09/input/example0 | 5 ++ 2021/day09/input/input | 100 +++++++++++++++++++++ 2021/day09/src/main.rs | 177 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 343 insertions(+) create mode 100644 2021/day09/Cargo.lock create mode 100644 2021/day09/Cargo.toml create mode 100644 2021/day09/README.md create mode 100644 2021/day09/input/example0 create mode 100644 2021/day09/input/input create mode 100644 2021/day09/src/main.rs diff --git a/2021/day09/Cargo.lock b/2021/day09/Cargo.lock new file mode 100644 index 0000000..8aa567a --- /dev/null +++ b/2021/day09/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day09" +version = "0.1.0" diff --git a/2021/day09/Cargo.toml b/2021/day09/Cargo.toml new file mode 100644 index 0000000..15d9cf9 --- /dev/null +++ b/2021/day09/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day09" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2021/day09/README.md b/2021/day09/README.md new file mode 100644 index 0000000..b8a77f0 --- /dev/null +++ b/2021/day09/README.md @@ -0,0 +1,46 @@ +https://adventofcode.com/2021/day/9 + +## \--- Day 9: Smoke Basin --- + +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: + +[code] + + 2 _1_ 9994321 _0_ + 3987894921 + 98 _5_ 6789892 + 8767896789 + 989996 _5_ 678 + +[/code] + +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?_ + diff --git a/2021/day09/input/example0 b/2021/day09/input/example0 new file mode 100644 index 0000000..6a74ad9 --- /dev/null +++ b/2021/day09/input/example0 @@ -0,0 +1,5 @@ +2 _1_ 9994321 _0_ +3987894921 +98 _5_ 6789892 +8767896789 +989996 _5_ 678 diff --git a/2021/day09/input/input b/2021/day09/input/input new file mode 100644 index 0000000..1b2c943 --- /dev/null +++ b/2021/day09/input/input @@ -0,0 +1,100 @@ +3498899019878754677899876434987898910234679986778932468999412767899921249978987543456799987899987876 +4597678929765833445943989759976567891465798765869893459997323459999890198767898792347899876999876645 +9986567898654421237891094998765347976587987663656789598986537568998789397646999989499998765899865434 +8763456799543210948942123999654236897799876542345699987987656789987658989534789879987899986789996323 +9852165987654399899653439899954345679899988651234799895698967899896547678965698767996789498896987534 +7541034598765989789864598789865466789998798742398986744569878998765432567896789459875489699954598976 +5432123459879875678975798677976567997897659876567895432979999549898543456789992359876578976543239987 +6543334599989954567896987556988678956798543987678986759898989921987676567893210123987799989876136799 +8654456789999843456789875445999989239987562398989099898787678899898797688954321254599893498964345689 +9875598899988732347898654333878992198765421239699124987685457789759899789875434675679901987895496793 +2986789999876521456987543212668943019843210134568949986545345697545999899986545786789929876789989932 +1987998798765435587896432101457892198767521235679998697632158789434589999987656799999899965396879321 +0299899659876656678987545232345793899899432349789876598794377895323478998798867988989789654245568910 +1298778943987887889998654353476965789976545498990997469876456789212567896569879877875678965123457891 +2979667892398999998998765467987899896989769987991984367989767994346789965456998766434789996534968932 +9867458943489023457899976699798999935799898956789875457999879976557898654356789954321246789649899543 +7654347895678934668901989789559789424589987645698989598989991397968997655246699865310137898659797665 +9765236896789549789542999896445696537679896435787897699678992989899876442123469954323245998798679789 +9896144589899998997659898991234589648998765323676798789567989878789989321012398767454356899897598999 +6941023478999867898798787889945678959899994212545699895429876767679998992534569898768769986996456789 +5432124567989756789898656667896789998789789301234589997698765654598977989645678999899978975987867899 +6553734679876545899997543556789893987674679912547678998987654423987865678959889996945989964598998998 +7696545989997656789987632345899932398543467894758989899876543319876434567896999985436799893239989987 +8987656899998967893098641012799541987656878976769998767987432109965323458945678977321298789549878966 +9399897978999878932159892323678992399787989497878999654597644298764212969434767965410989678959769345 +1298969459986989543246993934568989459898991298989899543459756789872101894325457894329877567897657239 +2987654349895498754347989896679678967999432989796798432349897999989237789212399965698765435689642128 +9899765459679999899499876789894569999998999876655987321234998999994345678924987897987654323899951037 +9765989998567899998989924678943456987897978965434595210123489998765456789434976789999766445999872156 +9834599887456789887978913459652349876566467899323984321235678999876867896559875689999878576789653245 +8945798765387898765459904589101259865454348678919876533546789999998978997997654677895989687999877656 +7896999643228999876246895678912346965321234589323989854689899987799989989876543456964598798934988767 +6989898954019987542134989789924956987540455695456798765789999875689997878987651348976799899127699978 +5876797892123498431013778999875789998432567897978899979897899954578986768998910256899987977934569989 +4345676889234599545124567898976990976545778989899999989956598768678965456789321345698786556899698792 +3257345678945987656234579976999891987657889679789998797643459879789874345895432566987675345998976543 +2101234689656998764346889345789799998768996598699987698764769998999985456976543456989554234767897794 +3212345699987899885456793219897678899889865487589997569879898987999876869899676579975433123456789999 +5333459999898989876567899398923456789999654396467895456989987986789989998798987898754321012345998798 +7569998789799876989688998987934567994598763212356789347597896565678998987677898989865432124456789697 +8698889676689999898799987756895678979999854323767892123456998424799986976545799979879753234578994556 +9987674565578998769899976548789789459889876434789943254569876534999875568925689769998764345699543434 +9876543234467899656998767434678999398768976545678954565879987695789954321014578957889885456989432323 +1987652102345678943239654323489988999544987796789765776989698986898766535123489945679976769978921012 +0199863243458999453198765464599767898432098989899879887993569997909877645234567896798989998767892523 +9239954867567954321099986765678956987643129878901991998921345998912998784345678989987698765452679434 +8998767898689765692987987876789545698754298767899892359210167899439999895567899778996579876321567999 +7899878998799876989875598999899959798767987656789789459321379997698987987678965656889456985432345678 +6895989469902997976753459899999898999879876545345678998932998999987696799889654345678999976569496789 +5694398979899889765442356789398787899996999631234789877899887899876565679998767976789988997998989994 +3789457898798678954321467892197676789975698742649895756798796796543434568999898987899967989987879893 +4567967987656567965435698989986545678954987653458954247986545965432123457998989298989855679875658789 +7689878998943456896546789679876434589543398954567932123965437896543437689986679019876744598654345696 +8789989999732345989687894598764323678932198768799899439876545987859549898775568999865432987643256795 +9991099987621265778998943569843212367893349879898798945987687899998956798654348789886540198732134894 +9989129876540124567979964579976301456789459989989667896798789945987897899886234598765431469543456902 +9878939986521569879769875798765412348996598998976456789899893239896689998765495679986562359876587893 +8769898765432478989654986969876523657899987697654367896934991098765568999886788797987679767989698954 +7659769876546599697923999853987798769998765498765478945795989139954457899997899896598899898999899995 +7649853987658943466899899764799899878909964349876567899979878998732356789998945997439934959789996986 +6534954599767892355998798765679934989219875656987978998968967789540245699999659986321012345698785497 +5429765679878910234597659878794325299924998787898989997956545678954357999898798765432129596987654329 +3212987794989321296789543989943210199895989899959799976844234569765456789789999976573298989898843212 +3101498943495433387997642396794321989789875935345679865432143568976789997657989899954987879789943209 +4212349932398544499896521345689439778678954321236789987545012379899899754349879767899896768678999998 +4363457893987659598789432467896598653578965432447892399653123456792998965598765456789765454579988787 +9456789954598998987679943598987989432345696643456890198764334569891987897899894323898754323459879656 +8769899866789997656567894789998976545456789754567899239895456678999865679999989219989843212398765545 +9997998988999876543456789898789998666567999765679978945976578989987654567979678998765432101987654234 +9886797999498765432326678987678899898678978976789669957897689999876543568964569999986954312398765101 +9765656789319854321014567896566789979989767897893459898998797999998662789543467892199875429459893212 +7654545678998765432123459975445698654393456789912399789019896798987653497651498993246976598999954343 +8943234567929876543275678954323459543212767893201988689323987987798765689320239789345987976789876458 +9895395678912989654586789995445668986543468954329876578939999876549876795432445678967899875345987967 +8796989989101292986797899987856899997854578965934985467898898765432998997544556789878986543234599898 +7679979893212391097898968998967899998765678979899876328246789986521019789678967898999598632123498799 +6598767789324989998929459999998999879876899998798765410135690198745123678989878967965439643245987689 +5432545689939878899102399898789998965987999987659876721248791987656234567899989656896019865459976578 +4321234567899767789293989765698987894299689998743987533367989998754345678999991347992139876798765469 +3210355879999645678989978974987876989103569879651987544569878999876556799778930456789246998999864345 +4323796789878924567977567895986645879212398765510198656789969899987667894569321367894356979987543234 +6435697896567895979865457989995434567923999864323498767899656789798798923498936568965469865698965676 +9876789923456896893974345678976312459899898765434569898998767896679899014567899689876598754349876789 +9987895312345797954985657789875401346789799877555678999439898934599984323678998796998789743210989896 +7899986453456998969876767893986212468998678988669899878924999623459876544567929965349899655439898965 +6432097568967899978987889901297326579765459599778965767895989510569998697678909893234987996598767464 +6593198789898945899899997892398438989899679499989954655689879431458798789789998789399656789679955353 +9989349999769236798789486899459549992998792987699893244588968942345679899899857678988745898798843212 +8878959898954126797678365678998757891369990996548789123467957793459798910998743569976324999987654523 +7967899767893235986543234769999898990156789875437678965678945689598987892987632457895436789998787634 +5456998656994467897652123456893969789245698765323569896789234579987696789765421346789597899869898745 +4349876545989578999653245767892345679367899972103456789892124569876554998653210145699989997654949856 +3234987439878989398769356978901956789878999864212389899943434598765432359986321234899878976543234987 +2136796545967893219898967899899897991989789974363478999854545998654321239875434345998767975432124598 +6545987659878999423987998999776799890195698765455569298765669899766510129876589456789656896594234599 +7659899867999988939876789988645698799234589876566689129879898769854321234987676567899545699989995678 +9998654978989877898765899876434789678945678987679791012989987655987642345698987899998732488979789789 +9876543989876865789996999995321234567896889798789895423497896543499873486789999978987521267965678990 +2995432598765934456789398765452345689997897659892986434986987632198764678999876569876410149894569521 +1986543497654321345891239976563456893198976543901296549765498743459876789101983469865321235789789433 diff --git a/2021/day09/src/main.rs b/2021/day09/src/main.rs new file mode 100644 index 0000000..31e0c15 --- /dev/null +++ b/2021/day09/src/main.rs @@ -0,0 +1,177 @@ +use std::collections::HashSet; +use std::io::stdin; +use std::io::BufRead; + +fn main() { + let arg = std::env::args().nth(1).unwrap_or("part2".to_string()); + match arg.as_str() { + "part1" => part1(), + _ => part2(), + } +} + +fn part1() { + println!("Part 1"); + let mut numbers = Vec::new(); + let mut width = 0; + let mut height = 0; + for line in stdin().lock().lines() { + let line = line.unwrap().replace(" ", "").replace("_", ""); + width = line.len(); + println!("{}", line); + + let mut parsed: Vec = line + .chars() + .map(|c| c.to_string().parse().unwrap()) + .collect(); + numbers.append(&mut parsed); + height += 1; + } + + dbg!(width, height); + + let field = Field::new(numbers, width, height); + + let mut risk_level: i32 = 0; + + for x in 0..height { + for y in 0..width { + let value = field.get((x, y)); + let neighbors = field.neighbors((x, y)); + if neighbors.iter().all(|&n| n > value) { + risk_level += 1 + *value as i32; + print!("\x1b[31m{}\x1b[0m", value); + } else { + print!("{}", value); + } + } + println!(); + } + + dbg!(risk_level); +} + +fn part2() { + println!("Part 2"); + let mut numbers = Vec::new(); + let mut width = 0; + let mut height = 0; + for line in stdin().lock().lines() { + let line = line.unwrap().replace(" ", "").replace("_", ""); + width = line.len(); + println!("{}", line); + + let mut parsed: Vec = line + .chars() + .map(|c| c.to_string().parse().unwrap()) + .collect(); + numbers.append(&mut parsed); + height += 1; + } + + dbg!(width, height); + + let field = Field::new(numbers, width, height); + + let mut basin_sizes = Vec::new(); + + for x in 0..height { + for y in 0..width { + let value = field.get((x, y)); + let neighbors = field.neighbors((x, y)); + if neighbors.iter().all(|&n| n > value) { + basin_sizes.push(field.basin_size((x, y))); + print!("\x1b[31m{}\x1b[0m", value); + } else if *value == 9 { + print!("\x1b[33m{}\x1b[0m", value); + } else { + print!("\x1b[37m{}\x1b[0m", value); + } + } + println!(); + } + + basin_sizes.sort(); + dbg!(&basin_sizes); + + let solution = basin_sizes.iter().rev().take(3).fold(1, |acc, el| acc * el); + dbg!(solution); +} + +struct Field { + width: usize, + height: usize, + numbers: Vec, +} + +impl<'a> Field { + fn new(numbers: Vec, width: usize, height: usize) -> Field { + Field { + width, + height, + numbers, + } + } + + fn get(&'a self, pos: (usize, usize)) -> &'a u8 { + let (x, y) = pos; + let idx = x * self.width + y; + self.numbers.get(idx).unwrap() + } + + fn neighbor_coords(&'a self, pos: (usize, usize)) -> Vec<(usize, usize)> { + let (x, y) = pos; + let mut coords = Vec::new(); + let is_top = x == 0; + let is_bot = x == self.height - 1; + let is_left = y % self.width == 0; + let is_right = (y + 1) % self.width == 0; + + if !is_top { + coords.push((x - 1, y)); + } + if !is_bot { + coords.push((x + 1, y)); + } + if !is_left { + coords.push((x, y - 1)) + } + if !is_right { + coords.push((x, y + 1)) + } + coords + } + + fn neighbors(&'a self, pos: (usize, usize)) -> Vec<&'a u8> { + self.neighbor_coords(pos) + .iter() + .map(|&pos| self.get(pos)) + .collect() + } + + fn basin_size(&self, pos: (usize, usize)) -> i32 { + let mut size = 0; + let mut coords_to_check = HashSet::new(); + let mut coords_checked = HashSet::new(); + + coords_to_check.insert(pos); + + while !coords_to_check.is_empty() { + let pos = *coords_to_check.iter().next().unwrap(); + coords_to_check.remove(&pos); + coords_checked.insert(pos); + if *self.get(pos) == 9 { + continue; + } + size += 1; + let neighbor_set = HashSet::from_iter(self.neighbor_coords(pos)); + coords_to_check.extend(&neighbor_set - &coords_checked); + // for neighbor in self.neighbor_coords(pos) { + // if !coords_checked.contains(neighbor){ + // coords_to_check.add(neighbor) + // } + // } + } + size + } +}