diff options
Diffstat (limited to 'src/2022/5/mod.rs')
-rw-r--r-- | src/2022/5/mod.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/2022/5/mod.rs b/src/2022/5/mod.rs new file mode 100644 index 0000000..74e4285 --- /dev/null +++ b/src/2022/5/mod.rs @@ -0,0 +1,141 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +use crate::prelude::*; + +#[derive(Default)] +pub struct Pile(Vec<char>); + +impl Pile { + fn move_from(&mut self, other: &mut Self, n: usize) { + for _ in 0..n { + self.0.push(other.0.pop().unwrap()); + } + } + + fn unshift(&mut self, c: char) { + self.0.insert(0, c); + } + + fn push(&mut self, c: char) { + self.0.push(c); + } + + fn pop(&mut self) -> Option<char> { + self.0.pop() + } + + fn top(&self) -> Option<char> { + self.0.last().copied() + } +} + +struct Instruction { + count: usize, + from: usize, + to: usize, +} + +pub struct Crates { + piles: Vec<Pile>, + instructions: Vec<Instruction>, +} + +pub fn parse(fh: File) -> Result<Crates> { + let mut lines = parse::lines(fh); + let mut piles: Vec<Pile> = vec![]; + + for line in lines.by_ref() { + if line.starts_with(" 1 ") { + break; + } + + let pile_count = (line.len() + 1) / 4; + piles.resize_with(pile_count, Default::default); + + for (pile_idx, pile) in piles.iter_mut().enumerate() { + let idx = pile_idx * 4; + assert!([' ', '['].contains(&line.chars().nth(idx).unwrap())); + let crate_name = line.chars().nth(idx + 1).unwrap(); + if crate_name != ' ' { + pile.unshift(crate_name); + } + assert!([' ', ']'].contains(&line.chars().nth(idx + 2).unwrap())); + assert!([Some(' '), None].contains(&line.chars().nth(idx + 3))); + } + } + + assert_eq!(lines.next().unwrap(), ""); + + let mut instructions = vec![]; + for line in lines { + let captures = regex_captures!( + r"^move ([0-9]+) from ([0-9]+) to ([0-9]+)$", + &line + ) + .unwrap(); + let count = captures[1].parse().unwrap(); + let from = captures[2].parse().unwrap(); + let to = captures[3].parse().unwrap(); + instructions.push(Instruction { count, from, to }); + } + + Ok(Crates { + piles, + instructions, + }) +} + +fn part1_str(mut crates: Crates) -> Result<String> { + for Instruction { count, from, to } in crates.instructions { + for _ in 0..count { + let c = crates.piles[from - 1].pop().unwrap(); + crates.piles[to - 1].push(c); + } + } + Ok(crates + .piles + .iter() + .map(|pile| pile.top().unwrap()) + .collect()) +} + +pub fn part1(crates: Crates) -> Result<i64> { + println!("{}", part1_str(crates)?); + Ok(0) +} + +fn part2_str(mut crates: Crates) -> Result<String> { + for Instruction { count, from, to } in crates.instructions { + let mut tmp = vec![]; + for _ in 0..count { + let c = crates.piles[from - 1].pop().unwrap(); + tmp.push(c); + } + for c in tmp.iter().copied().rev() { + crates.piles[to - 1].push(c); + } + } + Ok(crates + .piles + .iter() + .map(|pile| pile.top().unwrap()) + .collect()) +} + +pub fn part2(crates: Crates) -> Result<i64> { + println!("{}", part2_str(crates)?); + Ok(0) +} + +#[test] +fn test() { + assert_eq!( + part1_str(parse(parse::data(2022, 5).unwrap()).unwrap()).unwrap(), + "PSNRGBTFT" + ); + assert_eq!( + part2_str(parse(parse::data(2022, 5).unwrap()).unwrap()).unwrap(), + "BNTZFPMMW" + ); +} |