From 95df0a175eb19b996d63f7f14697a139fbf18c17 Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Mon, 5 Dec 2022 11:24:15 +0100 Subject: [PATCH] day(05): add initial version Signed-off-by: Matej Focko --- samples/day05.txt | 9 +++ src/bin/day05.rs | 155 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 samples/day05.txt create mode 100644 src/bin/day05.rs diff --git a/samples/day05.txt b/samples/day05.txt new file mode 100644 index 0000000..e98aba4 --- /dev/null +++ b/samples/day05.txt @@ -0,0 +1,9 @@ + [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 \ No newline at end of file diff --git a/src/bin/day05.rs b/src/bin/day05.rs new file mode 100644 index 0000000..39f47fd --- /dev/null +++ b/src/bin/day05.rs @@ -0,0 +1,155 @@ +use std::cmp::max; +use std::str::FromStr; + +use aoc_2022::*; + +use color_eyre::eyre::{Report, Result}; +use itertools::Itertools; +use tracing::*; +use tracing_subscriber::EnvFilter; + +#[derive(Debug)] +struct Move { + count: usize, + from: usize, + to: usize, +} + +impl FromStr for Move { + type Err = Report; + + fn from_str(s: &str) -> Result { + let split_str: Vec<_> = s.split_whitespace().collect(); + let ints = vec![split_str[1], split_str[3], split_str[5]] + .iter() + .map(|x| x.parse::().unwrap()) + .collect_vec(); + + let (count, from, to) = (ints[0], ints[1], ints[2]); + + Ok(Move { count, from, to }) + } +} + +#[derive(Debug)] +struct Ship(Vec>, Vec); + +impl FromStr for Ship { + type Err = Report; + + fn from_str(s: &str) -> Result { + let split_s = s.split("\n\n").collect_vec(); + let (stacks_str, moves_str) = (split_s[0], split_s[1]); + + let mut stacks: Vec> = Vec::new(); + + stacks_str + .lines() + .rev() + .skip(1) + .map(|l| l.to_string() + " ") + .for_each(|l| { + l.chars().skip(1).step_by(4).enumerate().for_each(|(i, c)| { + if i >= stacks.len() { + stacks.push(Vec::new()); + } + + if c != ' ' { + stacks[i].push(c); + } + }); + }); + + let moves = strings_to_structs(moves_str.lines()); + + Ok(Ship(stacks, moves)) + } +} + +type Input = Ship; +type Output = String; + +fn part_1(input: &Input) -> Output { + let Ship(stacks, moves) = input; + + let mut stacks = stacks.clone(); + + moves.iter().for_each(|m| { + for _ in 0..m.count { + if stacks[m.from - 1].is_empty() { + break; + } + + let popped = stacks[m.from - 1].pop().unwrap(); + stacks[m.to - 1].push(popped); + } + }); + + stacks.iter().fold(String::new(), |acc, stack| { + if let Some(c) = stack.last() { + acc + &c.to_string() + } else { + acc + } + }) +} + +fn part_2(input: &Input) -> Output { + let Ship(stacks, moves) = input; + + let mut stacks = stacks.clone(); + + moves.iter().for_each(|m| { + let size = stacks[m.from - 1].len(); + let mut s = stacks[m.from - 1].split_off(max(0, size - m.count)); + stacks[m.to - 1].append(&mut s); + }); + + stacks.iter().fold(String::new(), |acc, stack| { + if let Some(c) = stack.last() { + acc + &c.to_string() + } else { + acc + } + }) +} + +fn parse_input(pathname: &str) -> Input { + file_to_string(pathname).parse::().unwrap() +} + +fn main() -> Result<()> { + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .with_target(false) + .with_file(true) + .with_line_number(true) + .without_time() + .compact() + .init(); + color_eyre::install()?; + + let input = parse_input("inputs/day05.txt"); + + info!("Part 1: {}", part_1(&input)); + info!("Part 2: {}", part_2(&input)); + + Ok(()) +} + +#[cfg(test)] +mod day_05 { + use super::*; + + #[test] + fn test_part_1() { + let sample = parse_input("samples/day05.txt"); + assert_eq!(part_1(&sample), "CMZ".to_string()); + } + + #[test] + fn test_part_2() { + let sample = parse_input("samples/day05.txt"); + assert_eq!(part_2(&sample), "MCD".to_string()); + } +}