diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 084ad4f..1870c7d 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -4,4 +4,4 @@ version = 3 [[package]] name = "advent-of-code" -version = "22.4.2" +version = "22.5.2" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0f705a7..d87b622 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "advent-of-code" -version = "22.4.2" +version = "22.5.2" edition = "2021" resolver = "2" @@ -38,3 +38,7 @@ path = "src/day03/main.rs" [[bin]] name = "day04" path = "src/day04/main.rs" + +[[bin]] +name = "day05" +path = "src/day05/main.rs" diff --git a/rust/src/day05/input.txt b/rust/src/day05/input.txt new file mode 100644 index 0000000..7875817 --- /dev/null +++ b/rust/src/day05/input.txt @@ -0,0 +1,514 @@ + [G] [D] [Q] +[P] [T] [L] [M] [Z] +[Z] [Z] [C] [Z] [G] [W] +[M] [B] [F] [P] [C] [H] [N] +[T] [S] [R] [H] [W] [R] [L] [W] +[R] [T] [Q] [Z] [R] [S] [Z] [F] [P] +[C] [N] [H] [R] [N] [H] [D] [J] [Q] +[N] [D] [M] [G] [Z] [F] [W] [S] [S] + 1 2 3 4 5 6 7 8 9 + +move 7 from 6 to 8 +move 5 from 2 to 6 +move 2 from 4 to 1 +move 1 from 4 to 5 +move 5 from 7 to 6 +move 7 from 6 to 3 +move 5 from 9 to 2 +move 6 from 2 to 3 +move 2 from 7 to 9 +move 20 from 3 to 1 +move 11 from 1 to 6 +move 1 from 9 to 8 +move 3 from 8 to 2 +move 8 from 1 to 5 +move 10 from 8 to 4 +move 7 from 6 to 4 +move 1 from 8 to 3 +move 8 from 1 to 7 +move 16 from 4 to 8 +move 1 from 9 to 8 +move 1 from 5 to 2 +move 4 from 7 to 4 +move 5 from 6 to 7 +move 1 from 6 to 1 +move 8 from 7 to 4 +move 1 from 6 to 9 +move 12 from 4 to 5 +move 3 from 2 to 5 +move 1 from 6 to 2 +move 1 from 3 to 7 +move 1 from 3 to 2 +move 1 from 9 to 3 +move 1 from 7 to 8 +move 1 from 7 to 5 +move 1 from 3 to 2 +move 4 from 5 to 7 +move 5 from 5 to 7 +move 1 from 4 to 3 +move 1 from 3 to 9 +move 3 from 1 to 8 +move 1 from 9 to 1 +move 2 from 2 to 1 +move 2 from 2 to 7 +move 8 from 8 to 1 +move 3 from 5 to 2 +move 8 from 7 to 5 +move 7 from 1 to 3 +move 3 from 1 to 7 +move 1 from 1 to 5 +move 1 from 3 to 7 +move 7 from 5 to 8 +move 2 from 2 to 8 +move 1 from 3 to 2 +move 1 from 2 to 4 +move 1 from 4 to 8 +move 13 from 8 to 1 +move 13 from 5 to 9 +move 2 from 5 to 2 +move 7 from 9 to 3 +move 12 from 8 to 3 +move 4 from 9 to 3 +move 1 from 3 to 4 +move 2 from 2 to 3 +move 1 from 1 to 6 +move 1 from 2 to 3 +move 1 from 5 to 9 +move 7 from 7 to 4 +move 10 from 1 to 8 +move 1 from 1 to 4 +move 1 from 9 to 5 +move 2 from 5 to 1 +move 1 from 6 to 5 +move 3 from 8 to 9 +move 5 from 4 to 3 +move 4 from 4 to 1 +move 7 from 1 to 6 +move 2 from 5 to 7 +move 35 from 3 to 4 +move 4 from 9 to 1 +move 19 from 4 to 8 +move 1 from 7 to 6 +move 1 from 9 to 2 +move 10 from 4 to 5 +move 2 from 4 to 7 +move 3 from 4 to 3 +move 1 from 2 to 8 +move 1 from 1 to 9 +move 3 from 3 to 6 +move 4 from 8 to 6 +move 4 from 5 to 2 +move 2 from 8 to 3 +move 3 from 5 to 9 +move 12 from 6 to 1 +move 8 from 8 to 6 +move 2 from 9 to 1 +move 1 from 4 to 1 +move 1 from 3 to 8 +move 3 from 7 to 8 +move 2 from 9 to 7 +move 1 from 6 to 7 +move 10 from 6 to 8 +move 4 from 2 to 5 +move 1 from 3 to 7 +move 7 from 5 to 7 +move 13 from 8 to 1 +move 29 from 1 to 4 +move 8 from 7 to 8 +move 1 from 1 to 3 +move 3 from 7 to 6 +move 1 from 1 to 9 +move 15 from 4 to 1 +move 1 from 3 to 6 +move 10 from 1 to 6 +move 10 from 6 to 7 +move 1 from 4 to 9 +move 1 from 9 to 1 +move 1 from 9 to 7 +move 6 from 7 to 8 +move 1 from 1 to 6 +move 5 from 6 to 5 +move 21 from 8 to 9 +move 5 from 1 to 9 +move 2 from 9 to 5 +move 3 from 5 to 6 +move 3 from 7 to 9 +move 4 from 4 to 6 +move 6 from 8 to 7 +move 6 from 6 to 3 +move 2 from 7 to 9 +move 1 from 7 to 2 +move 6 from 3 to 2 +move 1 from 6 to 4 +move 4 from 5 to 9 +move 1 from 4 to 5 +move 9 from 4 to 6 +move 7 from 6 to 4 +move 10 from 9 to 2 +move 5 from 7 to 5 +move 10 from 2 to 7 +move 2 from 5 to 4 +move 2 from 5 to 9 +move 4 from 9 to 4 +move 1 from 8 to 6 +move 7 from 7 to 2 +move 1 from 5 to 4 +move 2 from 7 to 1 +move 1 from 5 to 7 +move 3 from 6 to 2 +move 4 from 4 to 5 +move 1 from 2 to 7 +move 10 from 4 to 7 +move 3 from 7 to 3 +move 17 from 9 to 4 +move 1 from 1 to 4 +move 1 from 1 to 5 +move 5 from 2 to 7 +move 1 from 9 to 2 +move 5 from 4 to 8 +move 2 from 9 to 7 +move 4 from 8 to 1 +move 3 from 4 to 8 +move 1 from 2 to 5 +move 1 from 9 to 2 +move 6 from 4 to 8 +move 3 from 7 to 5 +move 1 from 4 to 9 +move 1 from 9 to 1 +move 3 from 1 to 9 +move 4 from 8 to 5 +move 2 from 9 to 8 +move 4 from 2 to 5 +move 8 from 7 to 2 +move 5 from 8 to 5 +move 2 from 7 to 8 +move 1 from 3 to 5 +move 1 from 1 to 2 +move 1 from 1 to 6 +move 2 from 3 to 6 +move 5 from 2 to 8 +move 4 from 7 to 1 +move 7 from 8 to 5 +move 1 from 1 to 5 +move 3 from 8 to 3 +move 1 from 9 to 3 +move 7 from 2 to 3 +move 2 from 2 to 8 +move 2 from 4 to 8 +move 1 from 8 to 5 +move 1 from 1 to 4 +move 2 from 4 to 7 +move 2 from 7 to 1 +move 3 from 2 to 3 +move 3 from 5 to 2 +move 1 from 8 to 3 +move 3 from 3 to 2 +move 5 from 2 to 1 +move 17 from 5 to 8 +move 9 from 8 to 1 +move 11 from 3 to 5 +move 8 from 8 to 5 +move 2 from 8 to 5 +move 16 from 1 to 4 +move 13 from 4 to 7 +move 6 from 5 to 2 +move 2 from 4 to 8 +move 5 from 7 to 9 +move 2 from 1 to 2 +move 7 from 7 to 1 +move 1 from 1 to 4 +move 1 from 9 to 8 +move 7 from 2 to 8 +move 1 from 4 to 7 +move 2 from 9 to 4 +move 1 from 4 to 1 +move 1 from 3 to 5 +move 2 from 9 to 8 +move 11 from 8 to 7 +move 2 from 6 to 5 +move 1 from 6 to 9 +move 1 from 1 to 9 +move 1 from 9 to 1 +move 4 from 1 to 4 +move 2 from 1 to 8 +move 1 from 1 to 2 +move 1 from 9 to 5 +move 2 from 4 to 3 +move 2 from 2 to 7 +move 2 from 3 to 9 +move 1 from 9 to 1 +move 1 from 9 to 1 +move 5 from 5 to 1 +move 19 from 5 to 6 +move 5 from 1 to 4 +move 1 from 2 to 9 +move 1 from 1 to 3 +move 7 from 5 to 8 +move 1 from 3 to 6 +move 8 from 7 to 3 +move 7 from 4 to 8 +move 3 from 8 to 5 +move 1 from 4 to 1 +move 1 from 9 to 4 +move 1 from 4 to 9 +move 1 from 5 to 2 +move 2 from 5 to 6 +move 2 from 8 to 2 +move 7 from 8 to 1 +move 1 from 1 to 7 +move 3 from 6 to 9 +move 2 from 3 to 2 +move 1 from 2 to 1 +move 1 from 8 to 7 +move 2 from 9 to 6 +move 2 from 9 to 5 +move 1 from 5 to 6 +move 1 from 2 to 8 +move 2 from 1 to 7 +move 1 from 4 to 3 +move 3 from 2 to 5 +move 7 from 1 to 3 +move 10 from 3 to 4 +move 3 from 5 to 4 +move 1 from 3 to 8 +move 3 from 3 to 2 +move 1 from 8 to 1 +move 1 from 1 to 3 +move 3 from 8 to 3 +move 5 from 4 to 6 +move 1 from 2 to 3 +move 4 from 6 to 4 +move 1 from 5 to 7 +move 4 from 3 to 4 +move 1 from 2 to 8 +move 12 from 7 to 6 +move 1 from 8 to 2 +move 2 from 2 to 7 +move 1 from 8 to 4 +move 23 from 6 to 3 +move 14 from 3 to 6 +move 15 from 4 to 6 +move 1 from 8 to 6 +move 10 from 3 to 7 +move 2 from 4 to 2 +move 11 from 7 to 8 +move 2 from 2 to 6 +move 44 from 6 to 9 +move 21 from 9 to 3 +move 12 from 3 to 6 +move 1 from 7 to 4 +move 1 from 4 to 7 +move 9 from 3 to 2 +move 2 from 8 to 6 +move 3 from 2 to 4 +move 17 from 9 to 1 +move 3 from 4 to 6 +move 2 from 2 to 9 +move 4 from 9 to 2 +move 10 from 6 to 9 +move 1 from 7 to 6 +move 4 from 9 to 5 +move 4 from 2 to 4 +move 14 from 1 to 5 +move 4 from 4 to 3 +move 3 from 2 to 9 +move 9 from 9 to 7 +move 1 from 2 to 5 +move 9 from 8 to 5 +move 8 from 7 to 2 +move 4 from 3 to 8 +move 5 from 6 to 2 +move 3 from 1 to 6 +move 1 from 7 to 1 +move 4 from 2 to 4 +move 3 from 6 to 4 +move 3 from 8 to 3 +move 13 from 5 to 2 +move 2 from 3 to 5 +move 12 from 5 to 9 +move 1 from 3 to 5 +move 1 from 5 to 9 +move 1 from 8 to 3 +move 4 from 9 to 5 +move 6 from 4 to 5 +move 12 from 9 to 7 +move 1 from 9 to 3 +move 1 from 3 to 2 +move 12 from 5 to 6 +move 12 from 7 to 2 +move 1 from 3 to 7 +move 1 from 4 to 8 +move 33 from 2 to 8 +move 1 from 7 to 5 +move 1 from 1 to 2 +move 4 from 5 to 4 +move 3 from 2 to 5 +move 34 from 8 to 6 +move 1 from 4 to 3 +move 1 from 5 to 7 +move 1 from 7 to 5 +move 3 from 4 to 9 +move 2 from 9 to 7 +move 1 from 9 to 4 +move 1 from 3 to 7 +move 1 from 5 to 8 +move 1 from 5 to 1 +move 1 from 5 to 7 +move 1 from 4 to 8 +move 1 from 1 to 4 +move 1 from 4 to 2 +move 3 from 7 to 5 +move 2 from 8 to 5 +move 1 from 2 to 8 +move 4 from 6 to 2 +move 1 from 8 to 6 +move 1 from 7 to 9 +move 29 from 6 to 7 +move 4 from 2 to 3 +move 2 from 5 to 8 +move 1 from 9 to 5 +move 2 from 8 to 1 +move 23 from 7 to 5 +move 2 from 6 to 1 +move 23 from 5 to 6 +move 1 from 3 to 6 +move 4 from 5 to 9 +move 2 from 1 to 3 +move 5 from 3 to 8 +move 2 from 6 to 5 +move 2 from 1 to 4 +move 1 from 9 to 8 +move 1 from 9 to 1 +move 1 from 4 to 6 +move 2 from 5 to 6 +move 6 from 7 to 8 +move 2 from 9 to 2 +move 18 from 6 to 5 +move 21 from 6 to 4 +move 1 from 1 to 6 +move 2 from 6 to 7 +move 2 from 7 to 9 +move 2 from 2 to 8 +move 7 from 4 to 3 +move 12 from 5 to 3 +move 1 from 9 to 5 +move 1 from 9 to 4 +move 6 from 5 to 2 +move 17 from 3 to 4 +move 3 from 4 to 3 +move 1 from 2 to 4 +move 5 from 2 to 8 +move 1 from 5 to 8 +move 19 from 8 to 7 +move 1 from 3 to 6 +move 1 from 8 to 4 +move 1 from 6 to 1 +move 15 from 4 to 6 +move 1 from 1 to 4 +move 3 from 3 to 5 +move 4 from 6 to 7 +move 1 from 4 to 7 +move 10 from 6 to 7 +move 16 from 4 to 5 +move 24 from 7 to 2 +move 8 from 7 to 8 +move 1 from 4 to 2 +move 6 from 8 to 7 +move 1 from 8 to 7 +move 1 from 6 to 9 +move 14 from 5 to 4 +move 9 from 7 to 8 +move 4 from 5 to 1 +move 2 from 1 to 5 +move 3 from 8 to 6 +move 2 from 6 to 9 +move 2 from 2 to 8 +move 6 from 2 to 7 +move 3 from 4 to 6 +move 1 from 3 to 4 +move 3 from 5 to 7 +move 1 from 6 to 9 +move 5 from 7 to 2 +move 4 from 9 to 1 +move 1 from 7 to 9 +move 9 from 8 to 4 +move 5 from 1 to 2 +move 2 from 6 to 1 +move 6 from 4 to 7 +move 1 from 7 to 3 +move 1 from 3 to 9 +move 1 from 9 to 7 +move 1 from 6 to 7 +move 9 from 4 to 5 +move 7 from 7 to 9 +move 3 from 7 to 5 +move 1 from 9 to 2 +move 6 from 9 to 8 +move 4 from 4 to 5 +move 1 from 4 to 2 +move 1 from 4 to 2 +move 2 from 1 to 2 +move 1 from 9 to 8 +move 10 from 2 to 4 +move 8 from 2 to 7 +move 12 from 2 to 9 +move 6 from 7 to 4 +move 1 from 1 to 2 +move 8 from 9 to 8 +move 7 from 5 to 1 +move 9 from 4 to 3 +move 14 from 8 to 4 +move 1 from 8 to 4 +move 1 from 1 to 5 +move 1 from 5 to 2 +move 3 from 2 to 4 +move 1 from 7 to 1 +move 1 from 7 to 3 +move 2 from 1 to 7 +move 3 from 5 to 7 +move 2 from 7 to 6 +move 1 from 6 to 5 +move 3 from 7 to 1 +move 1 from 6 to 8 +move 1 from 8 to 7 +move 1 from 3 to 6 +move 1 from 7 to 1 +move 4 from 1 to 4 +move 6 from 3 to 2 +move 3 from 1 to 2 +move 3 from 3 to 6 +move 3 from 2 to 6 +move 6 from 6 to 5 +move 1 from 1 to 4 +move 1 from 9 to 6 +move 5 from 2 to 1 +move 3 from 1 to 2 +move 2 from 9 to 8 +move 3 from 1 to 5 +move 1 from 9 to 7 +move 25 from 4 to 1 +move 1 from 1 to 7 +move 2 from 8 to 3 +move 13 from 1 to 9 +move 2 from 3 to 5 +move 8 from 5 to 9 +move 4 from 2 to 1 +move 2 from 6 to 7 +move 10 from 5 to 9 +move 4 from 7 to 2 +move 2 from 2 to 3 +move 9 from 9 to 2 +move 4 from 4 to 5 +move 4 from 5 to 4 +move 5 from 1 to 4 +move 10 from 4 to 5 +move 22 from 9 to 1 +move 2 from 2 to 7 +move 3 from 2 to 1 +move 6 from 2 to 6 +move 1 from 7 to 1 +move 10 from 5 to 7 +move 15 from 1 to 4 +move 13 from 1 to 5 +move 3 from 6 to 8 +move 1 from 8 to 9 \ No newline at end of file diff --git a/rust/src/day05/main.rs b/rust/src/day05/main.rs new file mode 100644 index 0000000..007200f --- /dev/null +++ b/rust/src/day05/main.rs @@ -0,0 +1,153 @@ +#![feature(iter_array_chunks)] + +const INPUT: &str = include_str!("input.txt"); + +mod part_1; +use part_1::part_1; +mod part_2; +use part_2::part_2; + +#[derive(Debug, Clone)] +pub(crate) struct Instruction { + origin: usize, + destination: usize, + amount: usize, +} + +impl std::fmt::Display for Instruction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "move {} from {} to {}", + self.amount, self.origin, self.destination + ) + } +} + +#[derive(Debug, Clone)] +pub(crate) struct ChallengeInput { + initial_state: Vec>, + instructions: Vec, +} + +fn parse_input(input: &'static str) -> ChallengeInput { + let (unparsed_instructions, unparsed_initial_state) = input + .lines() + .partition::, _>(|line| line.starts_with("move")); + + let mut initial_state = vec![]; + unparsed_initial_state + .iter() + .rev() + .filter(|line| line.contains('[')) + .for_each(|line| { + let mut array_chunks = line.chars().array_chunks::<4>(); + let mut idx = 0; + loop { + let Some([lbracket, char, _rbracket, _space]) = array_chunks.next() else { + break; + }; + for _ in 0..usize::saturating_sub(1 + 1 + idx, initial_state.len()) { + initial_state.push(vec![]); + } + + if lbracket != '[' { + idx += 1; + continue; + } + + initial_state[idx].push(char); + idx += 1; + } + let remainder = array_chunks.into_remainder().unwrap().collect::>(); + let last_char = remainder[1]; + drop(remainder); + if last_char != ' ' { + let length = initial_state.len(); + initial_state[length - 1].push(last_char); + } + }); + + let instructions = unparsed_instructions + .iter() + .map(|instruction| { + // println!("instruction={instruction}"); + let mut chars = instruction.chars().peekable(); + loop { + if match chars.peek() { + None => true, + Some(char) => char.is_numeric(), + } { + break; + } + chars.next(); + } + let mut amount = String::new(); + loop { + if match chars.peek() { + None => true, + Some(char) => !char.is_numeric(), + } { + break; + } + amount.push(chars.next().unwrap()); + } + // println!("Amount: {amount}"); + loop { + if match chars.peek() { + None => true, + Some(char) => char.is_numeric(), + } { + break; + } + chars.next(); + } + let mut origin = String::new(); + loop { + if match chars.peek() { + None => true, + Some(char) => !char.is_numeric(), + } { + break; + } + origin.push(chars.next().unwrap()); + } + loop { + if match chars.peek() { + None => true, + Some(char) => char.is_numeric(), + } { + break; + } + chars.next(); + } + let mut destination = String::new(); + loop { + if match chars.peek() { + None => true, + Some(char) => !char.is_numeric(), + } { + break; + } + destination.push(chars.next().unwrap()); + } + + Instruction { + origin: origin.parse().expect("Non-numeric input encountered"), + destination: destination.parse().expect("Non-numeric input encountered"), + amount: amount.parse().expect("Non-numeric input encountered"), + } + }) + .collect(); + + ChallengeInput { + initial_state, + instructions, + } +} + +pub fn main() { + let input = parse_input(INPUT); + part_1(input.clone()); + part_2(input); +} diff --git a/rust/src/day05/part_1.rs b/rust/src/day05/part_1.rs new file mode 100644 index 0000000..d6cb27a --- /dev/null +++ b/rust/src/day05/part_1.rs @@ -0,0 +1,40 @@ +pub(crate) fn part_1(input: crate::ChallengeInput) -> String { + let mut state = input.initial_state.clone(); + + for crate::Instruction { + origin, + destination, + amount, + } in input.instructions + { + let length = state[origin - 1].len(); + let (new_state, moved) = state[origin - 1].split_at(length - amount); + let new_state = new_state.to_vec(); + let mut moved = moved.to_vec(); + moved.reverse(); + + state[origin - 1] = new_state; + state[destination - 1].append(&mut moved); + } + + state + .iter() + .filter(|stack| !stack.is_empty()) + .map(|stack| stack.last().unwrap()) + .collect() +} + +#[cfg(test)] +mod tests { + const SAMPLE_INPUT: &str = include_str!("sample_input.txt"); + + #[test] + fn test_with_solution() { + assert_eq!(super::part_1(crate::parse_input(crate::INPUT)), "RTGWZTHLD"); + } + + #[test] + fn test_with_sample_solution() { + assert_eq!(super::part_1(crate::parse_input(SAMPLE_INPUT)), "CMZ"); + } +} diff --git a/rust/src/day05/part_2.rs b/rust/src/day05/part_2.rs new file mode 100644 index 0000000..1b0ccec --- /dev/null +++ b/rust/src/day05/part_2.rs @@ -0,0 +1,40 @@ +pub(crate) fn part_2(input: crate::ChallengeInput) -> String { + let mut state = input.initial_state.clone(); + + for crate::Instruction { + origin, + destination, + amount, + } in input.instructions + { + let length = state[origin - 1].len(); + let (new_state, moved) = state[origin - 1].split_at(length - amount); + let new_state = new_state.to_vec(); + let mut moved = moved.to_vec(); + // moved.reverse(); + + state[origin - 1] = new_state; + state[destination - 1].append(&mut moved); + } + + state + .iter() + .filter(|stack| !stack.is_empty()) + .map(|stack| stack.last().unwrap()) + .collect() +} + +#[cfg(test)] +mod tests { + const SAMPLE_INPUT: &str = include_str!("sample_input.txt"); + + #[test] + fn test_with_solution() { + assert_eq!(super::part_2(crate::parse_input(crate::INPUT)), "STHGRZZFR"); + } + + #[test] + fn test_with_sample_solution() { + assert_eq!(super::part_2(crate::parse_input(SAMPLE_INPUT)), "MCD"); + } +} diff --git a/rust/src/day05/sample_input.txt b/rust/src/day05/sample_input.txt new file mode 100644 index 0000000..e98aba4 --- /dev/null +++ b/rust/src/day05/sample_input.txt @@ -0,0 +1,9 @@ + [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 \ No newline at end of file