From 5a86a400efe4063db2ca0f2a820ae2ffbeb1a388 Mon Sep 17 00:00:00 2001 From: kageru Date: Mon, 5 Dec 2022 11:15:40 +0100 Subject: [PATCH] Add 2022/05 --- 2022/src/bin/day05.rs | 90 +++++++++++++++++++++++++++++++++++++------ 2022/src/teststuff.rs | 2 +- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/2022/src/bin/day05.rs b/2022/src/bin/day05.rs index 1138cdd..2006119 100644 --- a/2022/src/bin/day05.rs +++ b/2022/src/bin/day05.rs @@ -3,27 +3,93 @@ extern crate test; use aoc2022::{boilerplate, common::*}; const DAY: usize = 5; -type Parsed = Vec; +type Parsed = (Vec>, Vec); + +#[derive(Debug)] +struct Move { + n: usize, + src: usize, + dst: usize, +} fn parse_input(raw: &str) -> Parsed { - parse_nums(raw) + let mut lines = raw.lines(); + let mut raw_stacks = Vec::new(); + let stack_numbers = loop { + match lines.next() { + Some(line) if line.contains('[') => raw_stacks.push(line), + Some(line) => break line, + None => unreachable!(), + } + }; + let num_stacks = (stack_numbers.trim().bytes().last().unwrap() - b'0') as usize; + let mut stacks = vec![vec![]; num_stacks]; + for s in raw_stacks.iter().rev() { + for n in 0..num_stacks { + match s.as_bytes().get(1 + 4 * n) { + Some(b' ') | None => (), + Some(&c) => stacks[n].push(c), + } + } + } + let moves = lines + .skip(1) + .map(|l| { + let (n, pos) = l[5..].split_once(" from ").unwrap(); + let (src, dst) = pos.split_once(" to ").unwrap(); + Move { n: parse_num(n), src: parse_num::(src) - 1, dst: parse_num::(dst) - 1 } + }) + .collect(); + (stacks, moves) } -fn part1(parsed: &Parsed) -> usize { - unimplemented!() +fn part1((stacks, moves): &Parsed) -> String { + let mut stacks = stacks.to_owned(); + for mov in moves { + for _ in 0..(mov.n) { + let e = stacks[mov.src].pop().unwrap(); + stacks[mov.dst].push(e); + } + } + stacks.iter().filter_map(|s| s.last()).map(|&b| b as char).collect() } -fn part2(parsed: &Parsed) -> usize { - unimplemented!() +fn part2((stacks, moves): &Parsed) -> String { + let mut stacks = stacks.to_owned(); + let mut temp = Vec::new(); + for mov in moves { + // Sadly can’t drain from one into the other because the compiler doesn’t know + // src and dst are always different :feelsBadMan: + let start_index = stacks[mov.src].len() - mov.n; + temp.extend(stacks[mov.src].drain(start_index..)); + for e in temp.drain(..) { + stacks[mov.dst].push(e); + } + } + stacks.iter().filter_map(|s| s.last()).map(|&b| b as char).collect() } boilerplate! { - TEST_INPUT == "", + TEST_INPUT == +" [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", tests: { - part1: { TEST_INPUT => 0 }, - part2: { TEST_INPUT => 0 }, + part1: { TEST_INPUT => "CMZ" }, + part2: { TEST_INPUT => "MCD" }, }, - bench1 == 0, - bench2 == 0, - bench_parse: Vec::len => 0, + bench1 == "QMBMJDFTD", + bench2 == "NBTVTJNFJ", + bench_parse: check_input => 504, +} + +#[cfg(test)] +fn check_input((_, moves): &Parsed) -> usize { + moves.len() } diff --git a/2022/src/teststuff.rs b/2022/src/teststuff.rs index 155be89..a53f4f7 100644 --- a/2022/src/teststuff.rs +++ b/2022/src/teststuff.rs @@ -25,7 +25,7 @@ macro_rules! boilerplate { $($(paste::paste! { #[test] - fn [<$part _test_ $to>]() { + fn [<$part _test_ $to:lower>]() { let input = parse_input($tpi); assert_eq!($part(&input), $to); }