From ce2b10e9ba524205f127d3387e3ec026bccc2f8a Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 5 Dec 2022 19:17:38 +0200 Subject: Day 5 --- 2022/src/bin/day_5.rs | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 2022/src/bin/day_5.rs (limited to '2022/src/bin') diff --git a/2022/src/bin/day_5.rs b/2022/src/bin/day_5.rs new file mode 100644 index 0000000..f06012c --- /dev/null +++ b/2022/src/bin/day_5.rs @@ -0,0 +1,147 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{ + anychar, char as nom_char, line_ending, not_line_ending, u32 as nom_u32, + }, + combinator::map, + multi::separated_list1, + sequence::tuple, + IResult, +}; +use std::fs; + +fn main() -> Result<(), Box> { + let input = fs::read_to_string("inputs/day_5.txt")?; + let state = CraneState::parser(&input).unwrap().1; + + let mut state_part_1 = state.clone(); + while !state_part_1.done() { + state_part_1.process_next_instruction(false); + } + dbg!(state_part_1.read_top_row()); + + let mut state_part_2 = state.clone(); + while !state_part_2.done() { + state_part_2.process_next_instruction(true); + } + dbg!(state_part_2.read_top_row()); + + Ok(()) +} + +#[derive(Debug, PartialEq, Eq, Clone)] +struct CraneState { + towers: Vec, + instructions: Vec, +} + +#[derive(Debug, Default, PartialEq, Eq, Clone)] +struct Tower { + crates: Vec, +} + +#[derive(Debug, PartialEq, Eq, Clone)] +struct Instruction { + number: usize, + src: usize, + dest: usize, +} + +impl CraneState { + fn parser(input: &str) -> IResult<&str, CraneState> { + let single_crate = alt(( + map(tuple((tag("["), anychar, tag("]"))), |(_, c, _)| Some(c)), + map(tag(" "), |_| None), + )); + let crate_row = separated_list1(nom_char(' '), single_crate); + + map( + tuple(( + separated_list1(line_ending, crate_row), + line_ending, + not_line_ending, + line_ending, + line_ending, + separated_list1(line_ending, Instruction::parser), + )), + |(crate_rows, _, _, _, _, mut instructions)| { + let mut towers = Vec::new(); + for row in &crate_rows { + for (i, c) in row + .iter() + .enumerate() + .filter_map(|(i, c)| c.map(|some_c| (i, some_c))) + { + while i >= towers.len() { + towers.push(Tower::default()); + } + towers[i].crates.push(c); + } + } + for tower in &mut towers { + tower.crates.reverse(); + } + + instructions.reverse(); + CraneState { + towers, + instructions, + } + }, + )(input) + } + + fn process_next_instruction(&mut self, maintain_order: bool) { + let Some(instruction) = self.instructions.pop() else { + return + }; + let mut to_move = Vec::new(); + for _ in 0..instruction.number { + let Some(crate_to_move) = self.towers[instruction.src].crates.pop() else { + panic!("Invalid puzzle input: failed to get crate"); + }; + to_move.push(crate_to_move); + } + if maintain_order { + to_move.reverse(); + } + for crate_to_move in to_move { + self.towers[instruction.dest].crates.push(crate_to_move); + } + } + + fn done(&self) -> bool { + self.instructions.len() == 0 + } + + fn read_top_row(&self) -> String { + let mut res = String::new(); + for tower in &self.towers { + if let Some(top) = tower.crates.last() { + res.push(*top); + } + } + res + } +} + +impl Instruction { + fn parser(input: &str) -> IResult<&str, Instruction> { + map( + tuple(( + tag("move "), + nom_u32, + tag(" from "), + nom_u32, + tag(" to "), + nom_u32, + )), + |(_, number, _, src, _, dest)| Instruction { + number: number as usize, + src: (src - 1) as usize, + dest: (dest - 1) as usize, + }, + )(input) + } +} -- cgit v1.2.3