From 01f5df4774e4d11123fda7dd098151c284f6bef7 Mon Sep 17 00:00:00 2001 From: fuckwit Date: Sun, 26 Nov 2023 00:29:09 +0100 Subject: [PATCH] Solve year 2022 day 05 --- src/util/parse.rs | 62 +++++++++++++++++++++++++++++++++ src/year2022/day05.rs | 79 +++++++++++++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 25 deletions(-) diff --git a/src/util/parse.rs b/src/util/parse.rs index 8e93241..ff66ae1 100644 --- a/src/util/parse.rs +++ b/src/util/parse.rs @@ -12,10 +12,26 @@ impl<'a> Iterator for U32s<'a> { } } +pub struct I32s<'a> { + bytes: Bytes<'a>, +} + +impl<'a> Iterator for I32s<'a> { + type Item = i32; + + fn next(&mut self) -> Option { + try_parse_i32(&mut self.bytes) + } +} + pub trait ParseExt { fn parse_u32(&self) -> u32; fn u32s(&self) -> U32s<'_>; + + fn parse_i32(&self) -> i32; + + fn i32s(&self) -> I32s<'_>; } impl ParseExt for &str { @@ -31,6 +47,19 @@ impl ParseExt for &str { bytes: self.bytes(), } } + + fn parse_i32(&self) -> i32 { + match try_parse_i32(&mut self.bytes()) { + Some(num) => num, + None => panic!("unable to parse i32: {self}"), + } + } + + fn i32s(&self) -> I32s<'_> { + I32s { + bytes: self.bytes(), + } + } } fn try_parse_u32(bytes: &mut Bytes<'_>) -> Option { @@ -56,3 +85,36 @@ fn try_parse_u32(bytes: &mut Bytes<'_>) -> Option { } } } + +fn try_parse_i32(bytes: &mut Bytes<'_>) -> Option { + let mut fac = 1; + let mut n = loop { + let byte = bytes.next()?; + if byte == b'-' { + let byte = bytes.next()?; + let digit = byte.wrapping_sub(b'0'); + if digit < 10 { + fac = -1; + break digit as i32; + } + } + let digit = byte.wrapping_sub(b'0'); + + if digit < 10 { + break digit as i32; + } + }; + + loop { + let Some(byte) = bytes.next() else { + break Some(n * fac); + }; + let digit = byte.wrapping_sub(b'0'); + + if digit < 10 { + n = 10 * n + digit as i32; + } else { + break Some(n * fac); + } + } +} \ No newline at end of file diff --git a/src/year2022/day05.rs b/src/year2022/day05.rs index 455e050..649b955 100644 --- a/src/year2022/day05.rs +++ b/src/year2022/day05.rs @@ -1,11 +1,9 @@ -use std::collections::BTreeMap; - use crate::util::parse::ParseExt; -fn parse(input: &str) -> (BTreeMap>, Vec<[u32; 3]>) { - let mut crates: BTreeMap> = BTreeMap::new(); - let mut moves = vec![]; - let (board, moveset) = input.split_once("\n\n\n").expect("must be there"); +fn parse(input: &str) -> Option<(Vec>, impl Iterator + '_)> { + let (board, moveset) = input.split_once("\n\n")?; + let size = board.lines().last()?.u32s().count(); + let mut crates: Vec> = vec![vec![]; size + 1]; board.lines().for_each(|line| { if !line.contains('[') { @@ -16,35 +14,66 @@ fn parse(input: &str) -> (BTreeMap>, Vec<[u32; 3]>) { .enumerate() .filter(|(_idx, c)| c.is_ascii_uppercase()) .for_each(|(idx, c)| { - crates - .entry(((idx - 4) / 4) + 1) - .and_modify(|v| v.push(c)) - .or_insert(vec![]); + crates[((idx + 2) / 4) + 1].push(c); }); }); - crates.values_mut().for_each(|v| v.reverse()); + for v in crates.iter_mut() { + v.reverse(); + } - let moves = moveset - .lines() - .map(|line| { - let mut nums = line.u32s(); - [ - nums.next().expect("first num"), - nums.next().expect("second num"), - nums.next().expect("third num"), - ] - }) - .collect(); + let moves = moveset.lines().filter_map(|line| { + let mut nums = line.u32s(); + Some([nums.next()?, nums.next()?, nums.next()?]) + }); - (crates, moves) + Some((crates, moves)) } pub fn part1(input: &str) -> impl std::fmt::Display { - "" + let (mut crates, moves) = parse(input).expect("parsing failed"); + let mut out: Vec = vec![String::new(); crates.len()]; + + for m in moves { + let mut items = { + let mut items = Vec::with_capacity(m[0] as usize); + let from: &mut Vec = crates[m[1] as usize].as_mut(); + for _ in 0..m[0] { + items.push(from.pop().expect("AOC please don't hate us")); + } + items + }; + crates[m[2] as usize].append(&mut items); + } + + for v in crates.iter_mut().skip(1) { + out.push(v.pop().expect("yes").to_string()); + } + + out.join("") } pub fn part2(input: &str) -> impl std::fmt::Display { - "" + let (mut crates, moves) = parse(input).expect("parsing failed"); + let mut out: Vec = vec![String::new(); crates.len()]; + + for m in moves { + let mut items = { + let mut items = Vec::with_capacity(m[0] as usize); + let from: &mut Vec = crates[m[1] as usize].as_mut(); + for _ in 0..m[0] { + items.push(from.pop().expect("AOC please don't hate us")); + } + items.reverse(); + items + }; + crates[m[2] as usize].append(&mut items); + } + + for v in crates.iter_mut().skip(1) { + out.push(v.pop().expect("yes").to_string()); + } + + out.join("") } #[test]