diff options
| author | Reiner Herrmann <reiner@reiner-h.de> | 2022-12-05 14:19:50 +0100 |
|---|---|---|
| committer | Reiner Herrmann <reiner@reiner-h.de> | 2022-12-05 14:19:50 +0100 |
| commit | 7526b65381c7e60b9d45298be099e9a665494ec9 (patch) | |
| tree | 04d20ee6108451e5ae0966a2e137f4dc1744e048 /src/bin | |
| parent | 8080b91d88245dce76c1c879bc380a3395167b0a (diff) | |
day5
Diffstat (limited to 'src/bin')
| -rw-r--r-- | src/bin/day5.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/bin/day5.rs b/src/bin/day5.rs new file mode 100644 index 0000000..a5e28fd --- /dev/null +++ b/src/bin/day5.rs @@ -0,0 +1,113 @@ +use std::collections::VecDeque; +use regex::Regex; + +static DAY: u8 = 5; + +fn main() { + let input = advent::read_lines(DAY); + println!("{DAY}a: {}", find_top_crates(&input)); + println!("{DAY}b: {}", find_top_crates_9001(&input)); +} + +struct CrateMover { + instructions: Vec<Instruction>, + stacks: Vec<VecDeque<char>>, +} + +struct Instruction { + amount: usize, + from: usize, + to: usize, +} + +impl CrateMover { + fn new(input: &[String]) -> CrateMover { + let re_instruction = Regex::new("move ([0-9]+) from ([0-9]+) to ([0-9]+)").unwrap(); + + let mut instructions = Vec::new(); + let mut stacks = Vec::new(); + for line in input { + if let Some(cap) = re_instruction.captures(line) { + instructions.push(Instruction { + amount: cap[1].parse::<usize>().unwrap(), + from: cap[2].parse::<usize>().unwrap() - 1, + to: cap[3].parse::<usize>().unwrap() - 1, + }); + } + + if line.find('[').is_some() { + let chars = line.chars().collect::<Vec<_>>(); + for (index, chunk) in chars.chunks(4).enumerate() { + // chunk: "[x] " + let name = chunk[1]; + if name == ' ' { + // empty position + continue; + } + if index >= stacks.len() { + stacks.resize(index + 1, VecDeque::new()); + } + stacks[index].push_front(name); + } + } + } + + CrateMover { stacks, instructions } + } + + fn move_crates(&mut self) { + for instruction in &self.instructions { + for _ in 0 .. instruction.amount { + let name = self.stacks[instruction.from].pop_back().expect("Stack has no crate"); + self.stacks[instruction.to].push_back(name); + } + } + } + + fn move_crates_9001(&mut self) { + for instruction in &self.instructions { + let drain_from = self.stacks[instruction.from].len() - instruction.amount; + let moved_stack = self.stacks[instruction.from].drain(drain_from ..).collect::<Vec<_>>(); + self.stacks[instruction.to].extend(moved_stack); + } + } +} + +fn find_top_crates(input: &[String]) -> String { + let mut cratemover = CrateMover::new(input); + cratemover.move_crates(); + cratemover.stacks.iter() + .map(|stack| stack.back().unwrap()) + .collect() +} + +fn find_top_crates_9001(input: &[String]) -> String { + let mut cratemover = CrateMover::new(input); + cratemover.move_crates_9001(); + cratemover.stacks.iter() + .map(|stack| stack.back().unwrap()) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + " [D] ".to_string(), + "[N] [C] ".to_string(), + "[Z] [M] [P]".to_string(), + " 1 2 3 ".to_string(), + "".to_string(), + "move 1 from 2 to 1".to_string(), + "move 3 from 1 to 3".to_string(), + "move 2 from 2 to 1".to_string(), + "move 1 from 1 to 2".to_string(), + ]; + + assert_eq!(find_top_crates(&input), "CMZ"); + assert_eq!(find_top_crates_9001(&input), "MCD"); + } +} |
