day(05): add initial version
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
6199872dcd
commit
95df0a175e
2 changed files with 164 additions and 0 deletions
9
samples/day05.txt
Normal file
9
samples/day05.txt
Normal file
|
@ -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
|
155
src/bin/day05.rs
Normal file
155
src/bin/day05.rs
Normal file
|
@ -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<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))
|
||||
}
|
||||
}
|
||||
|
||||
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::<Input>().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());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue