diff --git a/src/bin/d5p1.rs b/src/bin/d5p1.rs new file mode 100644 index 0000000..13d663a --- /dev/null +++ b/src/bin/d5p1.rs @@ -0,0 +1,25 @@ +use aoc22::{day5, util}; + +pub fn main() { + let mut arrangement = day5::parse_arrangement(&util::parse_input()); + + for inst in &arrangement.instructions { + for _ in 0..inst.num { + let box_ = arrangement + .stacks + .get_mut(inst.from) + .unwrap() + .pop_back() + .unwrap(); + arrangement.stacks.get_mut(inst.to).unwrap().push_back(box_); + } + } + + let top_boxes: String = arrangement + .stacks + .iter() + .map(|s| s.iter().next_back().unwrap()) + .collect(); + + println!("The top boxes are {}", top_boxes); +} diff --git a/src/day5.rs b/src/day5.rs new file mode 100644 index 0000000..cf7b6e4 --- /dev/null +++ b/src/day5.rs @@ -0,0 +1,97 @@ +use std::collections::VecDeque; + +use regex::Regex; + +#[derive(Debug)] +pub struct Instruction { + pub num: usize, + pub from: usize, + pub to: usize, +} + +#[derive(Debug)] +pub struct Arrangement { + pub stacks: Vec>, + pub instructions: Vec, +} + +fn parse_stack(line: &str) -> impl Iterator> + '_ { + line.as_bytes().chunks(4).map(|b| -> Option { + if *b.get(0).unwrap() as char == '[' { + Some(*b.get(1).unwrap() as char) + } else { + None + } + }) +} + +fn parse_instruction(line: &str) -> Instruction { + let re = Regex::new(r"move (\d+) from (\d+) to (\d+)").unwrap(); + let captures = re.captures(line).unwrap(); + Instruction { + num: captures.get(1).unwrap().as_str().parse().unwrap(), + from: captures.get(2).unwrap().as_str().parse::().unwrap() - 1, + to: captures.get(3).unwrap().as_str().parse::().unwrap() - 1, + } +} + +#[derive(Debug, Clone, Copy)] +enum ParseState { + Stacks, + StackNumbers, + Instructions, +} + +pub fn parse_arrangement(input: &String) -> Arrangement { + let lines: Vec<_> = input.lines().collect(); + let first_line = lines.get(0).unwrap(); + let length = first_line.len(); + // Each stack is 3 characters long, all but the last have a space following + // them. + assert!(length % 4 == 3); + let n_stacks = (length - 3) / 4 + 1; + let mut stacks: Vec> = Vec::with_capacity(n_stacks); + for _ in 0..n_stacks { + stacks.push(VecDeque::new()); + } + let mut instructions = Vec::new(); + + let mut state = ParseState::Stacks; + + for line in lines.iter() { + state = match state { + ParseState::Stacks => { + if line.contains('[') { + ParseState::Stacks + } else { + ParseState::StackNumbers + } + } + ParseState::StackNumbers => { + if line.starts_with("move") { + ParseState::Instructions + } else { + ParseState::StackNumbers + } + } + ParseState::Instructions => ParseState::Instructions, + }; + + match state { + ParseState::Stacks => { + for (i, box_) in parse_stack(line).enumerate() { + if let Some(c) = box_ { + stacks.get_mut(i).unwrap().push_front(c); + } + } + } + ParseState::StackNumbers => { /* Nothing to do here */ } + ParseState::Instructions => instructions.push(parse_instruction(line)), + } + } + + Arrangement { + stacks, + instructions, + } +} diff --git a/src/lib.rs b/src/lib.rs index 24d4a18..3655dcc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,5 @@ pub mod day1; pub mod day2; pub mod day3; pub mod day4; +pub mod day5; pub mod util;