diff options
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | input/day_5.txt | 512 | ||||
-rw-r--r-- | src/day_5.rs | 207 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 3 |
6 files changed, 731 insertions, 1 deletions
@@ -7,6 +7,7 @@ name = "advent_of_code_2022" version = "0.1.0" dependencies = [ "anyhow", + "indoc", ] [[package]] @@ -14,3 +15,9 @@ name = "anyhow" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + +[[package]] +name = "indoc" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" @@ -7,3 +7,4 @@ edition = "2021" [dependencies] anyhow = "1.0.66" +indoc = "1.0.7" diff --git a/input/day_5.txt b/input/day_5.txt new file mode 100644 index 0000000..922b345 --- /dev/null +++ b/input/day_5.txt @@ -0,0 +1,512 @@ +[W] [V] [P] +[B] [T] [C] [B] [G] +[G] [S] [V] [H] [N] [T] +[Z] [B] [W] [J] [D] [M] [S] +[R] [C] [N] [N] [F] [W] [C] [W] +[D] [F] [S] [M] [L] [T] [L] [Z] [Z] +[C] [W] [B] [G] [S] [V] [F] [D] [N] +[V] [G] [C] [Q] [T] [J] [P] [B] [M] + 1 2 3 4 5 6 7 8 9 + +move 2 from 8 to 4 +move 2 from 7 to 3 +move 2 from 9 to 2 +move 4 from 1 to 9 +move 1 from 7 to 8 +move 1 from 9 to 6 +move 6 from 6 to 1 +move 6 from 1 to 6 +move 2 from 7 to 1 +move 9 from 4 to 1 +move 6 from 2 to 7 +move 5 from 9 to 7 +move 7 from 3 to 7 +move 19 from 7 to 9 +move 1 from 7 to 1 +move 3 from 6 to 8 +move 4 from 5 to 6 +move 1 from 4 to 1 +move 2 from 5 to 2 +move 8 from 9 to 7 +move 1 from 5 to 1 +move 3 from 9 to 4 +move 1 from 4 to 9 +move 2 from 4 to 7 +move 1 from 7 to 6 +move 3 from 8 to 9 +move 17 from 1 to 7 +move 21 from 7 to 3 +move 4 from 6 to 2 +move 1 from 7 to 2 +move 8 from 9 to 2 +move 2 from 8 to 3 +move 1 from 1 to 7 +move 2 from 7 to 9 +move 1 from 6 to 1 +move 1 from 7 to 4 +move 1 from 1 to 2 +move 4 from 6 to 1 +move 1 from 9 to 2 +move 1 from 7 to 9 +move 1 from 4 to 1 +move 7 from 3 to 7 +move 6 from 2 to 8 +move 3 from 3 to 4 +move 1 from 8 to 4 +move 12 from 2 to 8 +move 2 from 9 to 2 +move 12 from 3 to 2 +move 12 from 8 to 6 +move 3 from 4 to 2 +move 19 from 2 to 8 +move 4 from 1 to 9 +move 1 from 3 to 8 +move 1 from 4 to 6 +move 1 from 2 to 4 +move 1 from 6 to 3 +move 8 from 9 to 6 +move 1 from 4 to 9 +move 1 from 3 to 1 +move 1 from 9 to 5 +move 11 from 6 to 3 +move 5 from 8 to 6 +move 14 from 6 to 9 +move 2 from 1 to 4 +move 3 from 8 to 1 +move 8 from 8 to 4 +move 3 from 3 to 4 +move 8 from 3 to 1 +move 9 from 8 to 2 +move 12 from 4 to 2 +move 12 from 9 to 3 +move 9 from 3 to 4 +move 1 from 5 to 3 +move 7 from 7 to 1 +move 2 from 9 to 1 +move 2 from 4 to 6 +move 16 from 2 to 6 +move 1 from 2 to 8 +move 10 from 1 to 4 +move 1 from 8 to 2 +move 4 from 1 to 6 +move 15 from 4 to 8 +move 1 from 4 to 2 +move 2 from 6 to 8 +move 5 from 2 to 8 +move 21 from 8 to 3 +move 6 from 1 to 3 +move 15 from 6 to 1 +move 1 from 2 to 1 +move 1 from 8 to 9 +move 15 from 1 to 3 +move 7 from 3 to 8 +move 1 from 7 to 9 +move 2 from 9 to 8 +move 2 from 3 to 7 +move 4 from 6 to 1 +move 2 from 7 to 8 +move 1 from 6 to 2 +move 4 from 8 to 3 +move 2 from 4 to 8 +move 1 from 2 to 1 +move 4 from 1 to 5 +move 3 from 5 to 8 +move 1 from 5 to 1 +move 12 from 8 to 3 +move 3 from 1 to 2 +move 17 from 3 to 5 +move 2 from 5 to 3 +move 15 from 5 to 1 +move 1 from 1 to 4 +move 17 from 3 to 2 +move 5 from 2 to 8 +move 17 from 3 to 6 +move 6 from 1 to 3 +move 5 from 1 to 6 +move 4 from 8 to 9 +move 10 from 3 to 8 +move 7 from 2 to 9 +move 2 from 6 to 3 +move 2 from 2 to 8 +move 1 from 1 to 4 +move 17 from 6 to 9 +move 13 from 8 to 2 +move 2 from 4 to 1 +move 1 from 6 to 7 +move 2 from 2 to 4 +move 8 from 2 to 7 +move 1 from 6 to 1 +move 4 from 7 to 9 +move 1 from 4 to 7 +move 1 from 4 to 6 +move 1 from 1 to 7 +move 5 from 2 to 4 +move 2 from 3 to 8 +move 6 from 7 to 1 +move 1 from 7 to 4 +move 11 from 9 to 7 +move 1 from 8 to 4 +move 8 from 1 to 2 +move 1 from 1 to 4 +move 1 from 1 to 9 +move 1 from 6 to 1 +move 1 from 8 to 4 +move 6 from 2 to 3 +move 1 from 1 to 3 +move 1 from 6 to 7 +move 1 from 4 to 6 +move 6 from 2 to 5 +move 7 from 3 to 4 +move 2 from 7 to 6 +move 2 from 7 to 3 +move 8 from 7 to 5 +move 3 from 6 to 7 +move 1 from 5 to 7 +move 1 from 7 to 5 +move 13 from 9 to 3 +move 1 from 3 to 8 +move 8 from 4 to 3 +move 3 from 5 to 1 +move 7 from 4 to 1 +move 5 from 1 to 4 +move 3 from 1 to 4 +move 2 from 1 to 8 +move 2 from 7 to 5 +move 2 from 8 to 9 +move 1 from 7 to 6 +move 1 from 8 to 7 +move 4 from 5 to 1 +move 1 from 7 to 2 +move 2 from 1 to 8 +move 1 from 2 to 1 +move 5 from 9 to 7 +move 3 from 9 to 4 +move 8 from 4 to 8 +move 6 from 8 to 5 +move 11 from 5 to 1 +move 3 from 4 to 2 +move 9 from 3 to 7 +move 6 from 7 to 2 +move 13 from 3 to 2 +move 3 from 8 to 1 +move 2 from 2 to 8 +move 1 from 6 to 7 +move 3 from 8 to 4 +move 9 from 1 to 5 +move 5 from 5 to 8 +move 2 from 8 to 4 +move 3 from 9 to 4 +move 2 from 8 to 2 +move 8 from 1 to 5 +move 8 from 7 to 9 +move 1 from 8 to 3 +move 15 from 5 to 9 +move 6 from 4 to 1 +move 1 from 7 to 2 +move 4 from 2 to 1 +move 1 from 3 to 4 +move 5 from 1 to 7 +move 3 from 7 to 3 +move 14 from 9 to 8 +move 1 from 4 to 8 +move 1 from 7 to 6 +move 2 from 4 to 5 +move 4 from 1 to 5 +move 1 from 6 to 5 +move 4 from 9 to 3 +move 5 from 3 to 7 +move 4 from 5 to 9 +move 1 from 3 to 7 +move 1 from 3 to 2 +move 4 from 5 to 2 +move 4 from 7 to 5 +move 4 from 2 to 1 +move 1 from 5 to 4 +move 7 from 9 to 7 +move 1 from 4 to 2 +move 1 from 5 to 8 +move 21 from 2 to 4 +move 1 from 9 to 8 +move 1 from 9 to 4 +move 3 from 4 to 1 +move 7 from 1 to 6 +move 1 from 5 to 1 +move 18 from 4 to 7 +move 1 from 5 to 8 +move 27 from 7 to 8 +move 1 from 7 to 3 +move 1 from 3 to 7 +move 1 from 7 to 2 +move 1 from 2 to 1 +move 42 from 8 to 9 +move 1 from 8 to 7 +move 1 from 8 to 2 +move 1 from 4 to 6 +move 1 from 2 to 9 +move 2 from 1 to 2 +move 1 from 7 to 3 +move 7 from 6 to 4 +move 4 from 9 to 6 +move 1 from 3 to 2 +move 1 from 2 to 7 +move 2 from 2 to 5 +move 1 from 8 to 4 +move 1 from 9 to 3 +move 5 from 4 to 7 +move 1 from 5 to 6 +move 1 from 5 to 9 +move 1 from 6 to 3 +move 1 from 7 to 5 +move 2 from 3 to 2 +move 22 from 9 to 7 +move 2 from 2 to 3 +move 18 from 7 to 9 +move 1 from 4 to 9 +move 1 from 1 to 4 +move 4 from 7 to 3 +move 4 from 3 to 2 +move 3 from 4 to 5 +move 1 from 2 to 4 +move 5 from 6 to 9 +move 1 from 5 to 3 +move 1 from 4 to 7 +move 2 from 5 to 1 +move 3 from 2 to 4 +move 1 from 5 to 6 +move 2 from 7 to 9 +move 1 from 6 to 8 +move 2 from 3 to 2 +move 2 from 4 to 7 +move 1 from 8 to 7 +move 1 from 4 to 6 +move 35 from 9 to 7 +move 13 from 7 to 3 +move 1 from 2 to 7 +move 1 from 2 to 5 +move 1 from 5 to 8 +move 1 from 8 to 5 +move 8 from 7 to 3 +move 1 from 6 to 4 +move 6 from 3 to 9 +move 1 from 1 to 9 +move 1 from 4 to 1 +move 14 from 9 to 8 +move 1 from 5 to 7 +move 16 from 3 to 2 +move 2 from 1 to 2 +move 1 from 9 to 2 +move 1 from 8 to 1 +move 1 from 1 to 3 +move 7 from 2 to 9 +move 6 from 9 to 8 +move 1 from 3 to 4 +move 3 from 7 to 6 +move 2 from 2 to 1 +move 1 from 4 to 7 +move 2 from 2 to 5 +move 1 from 9 to 6 +move 2 from 2 to 5 +move 2 from 6 to 2 +move 4 from 5 to 4 +move 5 from 2 to 6 +move 1 from 1 to 7 +move 1 from 1 to 2 +move 13 from 8 to 1 +move 2 from 8 to 4 +move 19 from 7 to 4 +move 3 from 1 to 6 +move 11 from 4 to 3 +move 2 from 7 to 9 +move 4 from 2 to 5 +move 2 from 9 to 5 +move 1 from 7 to 4 +move 2 from 5 to 7 +move 4 from 3 to 4 +move 3 from 4 to 1 +move 3 from 5 to 1 +move 9 from 6 to 4 +move 1 from 7 to 9 +move 1 from 7 to 5 +move 10 from 1 to 4 +move 1 from 9 to 6 +move 1 from 6 to 8 +move 32 from 4 to 5 +move 7 from 5 to 4 +move 27 from 5 to 9 +move 5 from 3 to 2 +move 3 from 2 to 8 +move 1 from 6 to 2 +move 8 from 4 to 9 +move 1 from 2 to 9 +move 8 from 8 to 6 +move 2 from 4 to 3 +move 1 from 2 to 3 +move 15 from 9 to 8 +move 4 from 1 to 4 +move 3 from 4 to 8 +move 6 from 9 to 7 +move 1 from 4 to 9 +move 8 from 8 to 2 +move 2 from 1 to 9 +move 2 from 7 to 9 +move 10 from 8 to 3 +move 6 from 2 to 6 +move 2 from 3 to 2 +move 6 from 6 to 3 +move 1 from 7 to 5 +move 8 from 3 to 2 +move 4 from 3 to 2 +move 1 from 3 to 5 +move 6 from 6 to 1 +move 4 from 3 to 7 +move 2 from 5 to 8 +move 3 from 7 to 5 +move 6 from 1 to 7 +move 1 from 3 to 4 +move 1 from 3 to 9 +move 10 from 7 to 4 +move 8 from 2 to 8 +move 11 from 9 to 5 +move 11 from 4 to 1 +move 5 from 2 to 6 +move 3 from 2 to 7 +move 11 from 1 to 6 +move 1 from 5 to 6 +move 8 from 5 to 4 +move 19 from 6 to 7 +move 3 from 7 to 9 +move 3 from 5 to 4 +move 1 from 2 to 5 +move 3 from 5 to 7 +move 8 from 9 to 6 +move 2 from 4 to 1 +move 1 from 1 to 9 +move 2 from 9 to 7 +move 6 from 6 to 2 +move 2 from 4 to 6 +move 4 from 8 to 6 +move 1 from 8 to 1 +move 7 from 6 to 7 +move 1 from 9 to 4 +move 5 from 8 to 4 +move 3 from 2 to 6 +move 4 from 6 to 4 +move 2 from 9 to 6 +move 3 from 2 to 9 +move 16 from 4 to 8 +move 1 from 6 to 8 +move 2 from 9 to 5 +move 1 from 9 to 7 +move 2 from 5 to 2 +move 1 from 4 to 6 +move 2 from 2 to 5 +move 1 from 9 to 6 +move 3 from 7 to 3 +move 7 from 7 to 8 +move 2 from 7 to 1 +move 3 from 8 to 5 +move 3 from 6 to 2 +move 4 from 7 to 4 +move 1 from 5 to 1 +move 1 from 5 to 7 +move 3 from 3 to 4 +move 5 from 1 to 4 +move 16 from 7 to 2 +move 5 from 4 to 7 +move 19 from 8 to 1 +move 11 from 2 to 9 +move 11 from 9 to 6 +move 2 from 1 to 6 +move 2 from 4 to 1 +move 5 from 4 to 6 +move 1 from 5 to 9 +move 1 from 9 to 6 +move 2 from 2 to 6 +move 1 from 5 to 4 +move 8 from 6 to 5 +move 16 from 1 to 6 +move 1 from 4 to 9 +move 3 from 2 to 9 +move 2 from 2 to 5 +move 2 from 5 to 8 +move 4 from 8 to 4 +move 4 from 9 to 7 +move 2 from 1 to 3 +move 5 from 6 to 4 +move 21 from 6 to 2 +move 9 from 7 to 3 +move 1 from 1 to 2 +move 1 from 5 to 3 +move 23 from 2 to 7 +move 1 from 7 to 5 +move 3 from 6 to 1 +move 9 from 4 to 5 +move 11 from 7 to 1 +move 2 from 3 to 4 +move 1 from 3 to 7 +move 1 from 4 to 1 +move 10 from 1 to 6 +move 5 from 7 to 1 +move 3 from 1 to 4 +move 7 from 1 to 7 +move 4 from 3 to 8 +move 4 from 7 to 4 +move 5 from 7 to 3 +move 2 from 4 to 9 +move 1 from 8 to 1 +move 4 from 4 to 1 +move 1 from 6 to 1 +move 1 from 6 to 5 +move 16 from 5 to 1 +move 2 from 5 to 7 +move 1 from 5 to 6 +move 2 from 8 to 2 +move 1 from 7 to 9 +move 3 from 9 to 5 +move 2 from 5 to 4 +move 6 from 7 to 1 +move 3 from 4 to 7 +move 1 from 8 to 6 +move 5 from 1 to 4 +move 1 from 6 to 1 +move 19 from 1 to 5 +move 1 from 7 to 6 +move 9 from 3 to 1 +move 6 from 6 to 5 +move 4 from 6 to 9 +move 3 from 9 to 4 +move 13 from 1 to 4 +move 1 from 3 to 1 +move 2 from 5 to 1 +move 1 from 2 to 3 +move 1 from 3 to 9 +move 4 from 5 to 4 +move 1 from 2 to 3 +move 1 from 3 to 5 +move 1 from 9 to 1 +move 1 from 9 to 5 +move 19 from 4 to 7 +move 4 from 1 to 6 +move 5 from 4 to 3 +move 3 from 6 to 1 +move 1 from 6 to 8 +move 2 from 1 to 6 +move 2 from 1 to 7 +move 2 from 6 to 3 +move 2 from 3 to 1 +move 8 from 7 to 6 +move 5 from 3 to 9 +move 2 from 4 to 9 +move 2 from 6 to 8 +move 10 from 7 to 2 +move 7 from 2 to 9 +move 1 from 8 to 9 +move 1 from 1 to 2 +move 2 from 9 to 3 +move 2 from 8 to 7 +move 1 from 1 to 6 +move 1 from 2 to 8 +move 2 from 2 to 5 +move 4 from 5 to 7 +move 5 from 6 to 1 +move 1 from 3 to 4 diff --git a/src/day_5.rs b/src/day_5.rs new file mode 100644 index 0000000..10eb2bc --- /dev/null +++ b/src/day_5.rs @@ -0,0 +1,207 @@ +use std::{ + fmt::Display, + ops::{Deref, DerefMut}, + str::FromStr, +}; + +use anyhow::{Context, Result}; + +#[derive(Debug)] +struct Procedure(Vec<Step>); + +impl Procedure { + fn run(self, mut stacks: Stacks, in_order: bool) -> Result<Stacks> { + for step in self.0 { + let mut move_stack = Vec::new(); + for _ in 0..step.count { + let cargo = stacks[step.from - 1] + .pop() + .ok_or_else(|| anyhow::anyhow!("ran out of cargo"))?; + move_stack.push(cargo) + } + + if in_order { + move_stack.reverse() + } + + stacks[step.to - 1].append(&mut move_stack); + } + Ok(stacks) + } +} + +impl FromStr for Procedure { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self> { + let mut procedure = Procedure(Vec::new()); + for (linenr, step) in s.lines().enumerate() { + procedure.push( + step.parse() + .context(format!("Error in procedure step {}: '{}'", linenr, step))?, + ) + } + Ok(procedure) + } +} + +impl Deref for Procedure { + type Target = Vec<Step>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Procedure { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[derive(Debug)] +struct Step { + count: usize, + from: usize, + to: usize, +} + +impl FromStr for Step { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self> { + let mut items = s.split_whitespace(); + Ok(Self { + count: items.next_chunk::<2>().unwrap().last().unwrap().parse()?, + from: items.next_chunk::<2>().unwrap().last().unwrap().parse()?, + to: items.next_chunk::<2>().unwrap().last().unwrap().parse()?, + }) + } +} + +#[derive(Debug)] +struct Stacks(Vec<Vec<char>>); + +impl Stacks { + fn top(mut self) -> String { + self.iter_mut().fold( + "".to_owned(), + |mut acc: String, s: &mut std::vec::Vec<char>| { + if let Some(c) = s.pop() { + acc.push(c) + } + acc + }, + ) + } +} + +impl Deref for Stacks { + type Target = Vec<Vec<char>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Stacks { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl FromStr for Stacks { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self> { + let mut stacks = Self(Vec::new()); + for line in s.lines().rev().skip(1) { + let mut chars = line.chars().skip(1).enumerate(); + loop { + let (stack, cargo) = match chars.next() { + Some((_, '[' | ']' | ' ')) => continue, + Some((index, c)) => (index / 4, c), + None => break, + }; + if stacks.len() < stack + 1 { + stacks.push(Vec::new()) + } + stacks[stack].push(cargo) + } + } + Ok(stacks) + } +} + +impl Display for Stacks { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Some(max_len) = self.0.iter().map(|v| v.len()).max() else { + return Ok(()) + }; + + for i in (0..max_len).rev() { + let mut cargos = Vec::new(); + for stack in &self.0 { + let cargo = match stack.get(i) { + Some(c) => format!("[{}]", c), + None => " ".to_owned(), + }; + cargos.push(cargo); + } + writeln!(f, "{}", cargos.join(" "))? + } + Ok(()) + } +} + +const DAY: u8 = 5; +const INPUT: &str = include_str!("../input/day_5.txt"); + +pub fn solve() -> Result<()> { + println!("day {}", DAY); + println!("part 1: {}", part_1(INPUT)?); + println!("part 2: {}", part_2(INPUT)?); + + Ok(()) +} + +pub fn part_1(input: &str) -> Result<String> { + let (stacks, procedure) = input.split_once("\n\n").unwrap(); + let stacks = Stacks::from_str(stacks)?; + let procedure = Procedure::from_str(procedure)?; + Ok(procedure.run(stacks, false)?.top()) +} + +pub fn part_2(input: &str) -> Result<String> { + let (stacks, procedure) = input.split_once("\n\n").unwrap(); + let stacks = Stacks::from_str(stacks)?; + let procedure = Procedure::from_str(procedure)?; + Ok(procedure.run(stacks, true)?.top()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_INPUT: &str = indoc::indoc! {r#" + [D] + [N] [C] + [Z] [M] [P] + 1 2 3 + + move 1 from 2 to 1 + move 3 from 1 to 3 + move 2 from 2 to 1 + move 1 from 1 to 2 + "#}; + + #[test] + fn test_part_1_example() -> Result<()> { + Ok(assert_eq!("CMZ", part_1(TEST_INPUT)?)) + } + + #[test] + fn test_part_2_example() -> Result<()> { + Ok(assert_eq!("MCD", part_2(TEST_INPUT)?)) + } +} @@ -1,6 +1,8 @@ #![feature(iterator_try_collect)] +#![feature(iter_next_chunk)] pub mod day_1; pub mod day_2; pub mod day_3; pub mod day_4; +pub mod day_5; diff --git a/src/main.rs b/src/main.rs index 1511ea6..547f1e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use advent_of_code_2022::{day_1, day_2, day_4, day_3}; +use advent_of_code_2022::{day_1, day_2, day_3, day_4, day_5}; use anyhow::Result; fn main() -> Result<()> { @@ -6,6 +6,7 @@ fn main() -> Result<()> { day_2::solve()?; day_3::solve()?; day_4::solve()?; + day_5::solve()?; Ok(()) } |