1
0
Fork 0
2022/src/bin/day05.rs
2023-01-06 20:00:52 +01:00

113 lines
2.6 KiB
Rust

use std::cmp::max;
use std::str::FromStr;
use aoc_2022::*;
type Input = Ship;
type Output = String;
#[derive(Debug)]
struct Move {
count: usize,
from: usize,
to: usize,
}
impl FromStr for Move {
type Err = Report;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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::<usize>().unwrap())
.collect_vec();
let (count, from, to) = (ints[0], ints[1], ints[2]);
Ok(Move { count, from, to })
}
}
#[derive(Debug)]
struct Ship(Vec<Vec<char>>, Vec<Move>);
impl FromStr for Ship {
type Err = Report;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<char>> = 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))
}
}
fn stacks_to_string(stacks: &[Vec<char>]) -> String {
stacks.iter().fold(String::new(), |acc, stack| {
if let Some(c) = stack.last() {
acc + &c.to_string()
} else {
acc
}
})
}
fn move_crates(input: &Input, one_by_one: bool) -> 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));
if one_by_one {
s.reverse();
}
stacks[m.to - 1].append(&mut s);
});
stacks_to_string(&stacks)
}
struct Day05;
impl Solution<Input, Output> for Day05 {
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
file_to_string(pathname).parse().unwrap()
}
fn part_1(input: &Input) -> Output {
move_crates(input, true)
}
fn part_2(input: &Input) -> Output {
move_crates(input, false)
}
}
fn main() -> Result<()> {
Day05::main()
}
test_sample!(day_05, Day05, "CMZ".to_string(), "MCD".to_string());