Compare commits

..

No commits in common. "72426e9163603167bf27f7e4fcdf1947c625ac47" and "0e475d9264b1147d02f78c6dc5a93010d94ccaa2" have entirely different histories.

3 changed files with 0 additions and 853 deletions

View File

@ -1,511 +0,0 @@
[G] [P] [M]
[V] [M] [W] [S] [Q]
[N] [N] [G] [H] [T] [F]
[J] [W] [V] [Q] [W] [F] [P]
[C] [H] [T] [T] [G] [B] [Z] [B]
[S] [W] [S] [L] [F] [B] [P] [C] [H]
[G] [M] [Q] [S] [Z] [T] [J] [D] [S]
[B] [T] [M] [B] [J] [C] [T] [G] [N]
1 2 3 4 5 6 7 8 9
move 2 from 4 to 2
move 6 from 9 to 7
move 4 from 7 to 2
move 2 from 4 to 1
move 2 from 6 to 7
move 1 from 3 to 8
move 4 from 7 to 1
move 2 from 3 to 2
move 3 from 8 to 5
move 3 from 1 to 4
move 12 from 2 to 5
move 2 from 6 to 8
move 12 from 5 to 8
move 3 from 7 to 9
move 18 from 8 to 9
move 2 from 8 to 6
move 3 from 2 to 3
move 14 from 9 to 4
move 1 from 1 to 3
move 7 from 9 to 3
move 1 from 2 to 1
move 8 from 4 to 5
move 5 from 6 to 3
move 2 from 7 to 9
move 3 from 4 to 9
move 4 from 9 to 6
move 4 from 6 to 1
move 8 from 4 to 6
move 10 from 1 to 2
move 13 from 3 to 2
move 17 from 5 to 9
move 2 from 5 to 1
move 9 from 9 to 7
move 1 from 3 to 6
move 2 from 1 to 8
move 11 from 2 to 4
move 5 from 6 to 8
move 1 from 6 to 3
move 1 from 1 to 4
move 3 from 8 to 6
move 3 from 2 to 8
move 9 from 7 to 9
move 4 from 4 to 7
move 1 from 9 to 5
move 15 from 9 to 7
move 7 from 8 to 3
move 1 from 5 to 6
move 2 from 6 to 9
move 8 from 2 to 6
move 3 from 4 to 3
move 1 from 2 to 5
move 4 from 9 to 3
move 1 from 3 to 4
move 13 from 6 to 2
move 1 from 5 to 1
move 4 from 4 to 9
move 6 from 3 to 2
move 11 from 2 to 7
move 6 from 3 to 4
move 3 from 3 to 2
move 1 from 3 to 4
move 1 from 1 to 3
move 3 from 9 to 2
move 1 from 3 to 1
move 4 from 7 to 1
move 1 from 9 to 5
move 5 from 1 to 4
move 11 from 2 to 4
move 1 from 5 to 3
move 1 from 2 to 3
move 12 from 4 to 2
move 2 from 7 to 2
move 7 from 4 to 3
move 5 from 4 to 1
move 7 from 7 to 6
move 4 from 1 to 8
move 1 from 8 to 5
move 8 from 3 to 2
move 4 from 7 to 4
move 13 from 7 to 1
move 2 from 8 to 6
move 5 from 4 to 9
move 1 from 3 to 6
move 1 from 5 to 8
move 1 from 2 to 9
move 4 from 2 to 6
move 2 from 8 to 6
move 10 from 1 to 3
move 4 from 9 to 4
move 2 from 1 to 3
move 5 from 2 to 9
move 4 from 9 to 2
move 1 from 1 to 2
move 13 from 2 to 4
move 15 from 4 to 5
move 3 from 6 to 8
move 8 from 3 to 8
move 1 from 4 to 2
move 14 from 5 to 1
move 1 from 5 to 4
move 1 from 4 to 2
move 8 from 6 to 7
move 3 from 6 to 2
move 2 from 9 to 1
move 8 from 8 to 7
move 9 from 1 to 5
move 7 from 5 to 3
move 14 from 7 to 9
move 2 from 2 to 3
move 7 from 2 to 1
move 1 from 6 to 1
move 4 from 9 to 2
move 8 from 3 to 6
move 2 from 4 to 3
move 4 from 3 to 5
move 5 from 5 to 7
move 2 from 6 to 9
move 6 from 6 to 2
move 4 from 2 to 3
move 1 from 6 to 2
move 2 from 7 to 8
move 13 from 9 to 5
move 2 from 7 to 1
move 14 from 1 to 5
move 15 from 5 to 7
move 3 from 8 to 7
move 5 from 3 to 5
move 6 from 5 to 7
move 4 from 1 to 7
move 1 from 2 to 5
move 3 from 2 to 8
move 11 from 5 to 2
move 10 from 7 to 1
move 1 from 3 to 4
move 10 from 2 to 9
move 1 from 5 to 8
move 6 from 7 to 3
move 1 from 4 to 6
move 2 from 3 to 8
move 1 from 2 to 1
move 4 from 3 to 9
move 3 from 1 to 6
move 2 from 7 to 1
move 1 from 5 to 6
move 1 from 3 to 8
move 4 from 1 to 4
move 5 from 2 to 9
move 3 from 1 to 4
move 18 from 9 to 7
move 4 from 8 to 4
move 3 from 1 to 2
move 1 from 9 to 7
move 1 from 4 to 7
move 1 from 6 to 2
move 1 from 2 to 5
move 25 from 7 to 3
move 7 from 4 to 2
move 8 from 7 to 9
move 4 from 8 to 6
move 1 from 8 to 5
move 4 from 6 to 5
move 2 from 9 to 5
move 3 from 5 to 8
move 4 from 6 to 4
move 12 from 3 to 5
move 11 from 3 to 2
move 13 from 5 to 8
move 4 from 9 to 6
move 7 from 4 to 9
move 2 from 6 to 2
move 12 from 2 to 7
move 1 from 6 to 3
move 1 from 5 to 6
move 2 from 5 to 3
move 15 from 8 to 6
move 4 from 6 to 7
move 1 from 5 to 1
move 10 from 2 to 8
move 8 from 8 to 3
move 8 from 6 to 8
move 2 from 7 to 6
move 9 from 9 to 7
move 8 from 8 to 9
move 1 from 1 to 3
move 1 from 2 to 7
move 7 from 3 to 1
move 3 from 8 to 5
move 3 from 1 to 6
move 7 from 9 to 2
move 2 from 3 to 7
move 5 from 7 to 9
move 17 from 7 to 5
move 2 from 7 to 6
move 10 from 6 to 3
move 1 from 1 to 3
move 6 from 9 to 3
move 1 from 2 to 9
move 2 from 7 to 9
move 2 from 9 to 7
move 1 from 5 to 8
move 1 from 8 to 5
move 6 from 2 to 5
move 1 from 6 to 1
move 5 from 3 to 5
move 1 from 6 to 8
move 1 from 7 to 9
move 2 from 9 to 3
move 15 from 5 to 2
move 2 from 1 to 8
move 2 from 3 to 7
move 2 from 8 to 3
move 3 from 5 to 9
move 1 from 8 to 6
move 1 from 9 to 6
move 3 from 7 to 6
move 17 from 3 to 4
move 1 from 1 to 2
move 6 from 2 to 9
move 16 from 4 to 1
move 4 from 6 to 8
move 9 from 5 to 6
move 8 from 6 to 2
move 2 from 9 to 5
move 2 from 3 to 5
move 1 from 6 to 2
move 1 from 4 to 8
move 14 from 1 to 3
move 8 from 5 to 3
move 20 from 3 to 1
move 1 from 8 to 2
move 1 from 9 to 6
move 1 from 6 to 7
move 1 from 7 to 3
move 22 from 1 to 2
move 3 from 3 to 6
move 27 from 2 to 8
move 2 from 2 to 8
move 2 from 6 to 9
move 2 from 9 to 4
move 2 from 4 to 8
move 1 from 1 to 3
move 14 from 8 to 5
move 1 from 3 to 9
move 3 from 9 to 2
move 5 from 2 to 8
move 10 from 2 to 9
move 1 from 6 to 7
move 1 from 7 to 5
move 7 from 5 to 2
move 2 from 9 to 2
move 1 from 6 to 2
move 2 from 9 to 5
move 3 from 5 to 6
move 6 from 5 to 3
move 1 from 5 to 6
move 4 from 3 to 9
move 2 from 9 to 8
move 3 from 9 to 5
move 23 from 8 to 1
move 2 from 6 to 1
move 1 from 5 to 7
move 2 from 3 to 5
move 2 from 9 to 5
move 4 from 9 to 7
move 2 from 9 to 4
move 1 from 5 to 4
move 5 from 8 to 5
move 2 from 6 to 2
move 3 from 7 to 3
move 1 from 3 to 4
move 3 from 2 to 8
move 4 from 1 to 6
move 2 from 6 to 3
move 4 from 1 to 2
move 3 from 8 to 1
move 13 from 2 to 5
move 4 from 3 to 2
move 14 from 5 to 7
move 5 from 2 to 7
move 18 from 7 to 9
move 4 from 4 to 7
move 2 from 5 to 4
move 17 from 9 to 5
move 1 from 9 to 1
move 1 from 7 to 2
move 5 from 7 to 2
move 18 from 1 to 4
move 1 from 7 to 3
move 1 from 3 to 6
move 2 from 1 to 3
move 1 from 6 to 5
move 2 from 6 to 8
move 1 from 8 to 9
move 1 from 8 to 3
move 13 from 4 to 5
move 1 from 1 to 6
move 3 from 2 to 4
move 1 from 6 to 1
move 3 from 2 to 9
move 3 from 3 to 1
move 5 from 4 to 5
move 30 from 5 to 3
move 1 from 4 to 6
move 1 from 9 to 8
move 1 from 9 to 6
move 21 from 3 to 7
move 3 from 1 to 6
move 1 from 1 to 4
move 1 from 9 to 6
move 1 from 8 to 2
move 1 from 3 to 6
move 1 from 9 to 3
move 5 from 4 to 8
move 1 from 2 to 4
move 9 from 5 to 7
move 2 from 5 to 9
move 2 from 8 to 2
move 2 from 6 to 3
move 1 from 4 to 1
move 4 from 3 to 8
move 2 from 9 to 2
move 4 from 2 to 6
move 1 from 1 to 4
move 2 from 6 to 9
move 2 from 5 to 4
move 1 from 3 to 1
move 1 from 1 to 3
move 2 from 9 to 1
move 5 from 3 to 5
move 1 from 1 to 8
move 4 from 6 to 4
move 5 from 5 to 6
move 18 from 7 to 5
move 1 from 3 to 4
move 12 from 7 to 5
move 15 from 5 to 6
move 1 from 5 to 8
move 1 from 3 to 7
move 1 from 1 to 2
move 1 from 2 to 4
move 1 from 7 to 9
move 2 from 8 to 2
move 1 from 2 to 4
move 4 from 4 to 2
move 1 from 2 to 1
move 1 from 9 to 8
move 4 from 6 to 4
move 3 from 2 to 6
move 1 from 2 to 6
move 8 from 4 to 3
move 1 from 1 to 3
move 6 from 6 to 1
move 1 from 3 to 6
move 5 from 1 to 7
move 10 from 5 to 9
move 3 from 9 to 8
move 7 from 6 to 2
move 1 from 7 to 8
move 3 from 5 to 8
move 3 from 6 to 2
move 6 from 8 to 9
move 1 from 5 to 3
move 2 from 3 to 1
move 2 from 4 to 8
move 6 from 6 to 9
move 1 from 1 to 4
move 17 from 9 to 2
move 1 from 4 to 1
move 2 from 7 to 8
move 1 from 9 to 8
move 3 from 8 to 4
move 3 from 1 to 4
move 9 from 8 to 2
move 1 from 8 to 4
move 12 from 2 to 7
move 4 from 7 to 4
move 1 from 8 to 1
move 10 from 4 to 2
move 3 from 3 to 2
move 1 from 9 to 7
move 11 from 7 to 3
move 1 from 3 to 1
move 2 from 3 to 9
move 1 from 3 to 7
move 2 from 1 to 9
move 1 from 6 to 5
move 7 from 3 to 6
move 1 from 7 to 3
move 3 from 3 to 4
move 1 from 5 to 7
move 2 from 4 to 3
move 2 from 4 to 8
move 1 from 7 to 6
move 2 from 6 to 8
move 1 from 9 to 2
move 1 from 9 to 5
move 1 from 5 to 1
move 1 from 8 to 6
move 1 from 3 to 2
move 4 from 6 to 1
move 5 from 1 to 4
move 11 from 2 to 4
move 2 from 8 to 2
move 1 from 8 to 9
move 27 from 2 to 5
move 4 from 6 to 3
move 3 from 2 to 4
move 2 from 5 to 9
move 1 from 5 to 7
move 2 from 9 to 5
move 14 from 4 to 7
move 2 from 4 to 7
move 3 from 4 to 8
move 4 from 3 to 1
move 4 from 1 to 8
move 2 from 3 to 9
move 2 from 9 to 3
move 7 from 8 to 9
move 1 from 3 to 8
move 2 from 3 to 2
move 25 from 5 to 9
move 1 from 5 to 8
move 1 from 8 to 7
move 26 from 9 to 1
move 23 from 1 to 5
move 7 from 9 to 7
move 1 from 9 to 8
move 1 from 9 to 2
move 5 from 7 to 1
move 20 from 5 to 6
move 1 from 7 to 6
move 2 from 5 to 3
move 1 from 8 to 6
move 21 from 6 to 8
move 1 from 6 to 4
move 1 from 1 to 7
move 2 from 1 to 6
move 1 from 1 to 3
move 1 from 2 to 5
move 1 from 2 to 6
move 2 from 7 to 6
move 6 from 7 to 9
move 3 from 1 to 2
move 17 from 8 to 1
move 1 from 4 to 1
move 2 from 6 to 9
move 3 from 8 to 9
move 2 from 3 to 7
move 2 from 9 to 8
move 4 from 7 to 3
move 4 from 3 to 4
move 2 from 5 to 8
move 4 from 8 to 4
move 3 from 6 to 8
move 18 from 1 to 5
move 1 from 3 to 4
move 3 from 2 to 4
move 5 from 9 to 1
move 10 from 7 to 5
move 5 from 1 to 3
move 5 from 3 to 5
move 5 from 4 to 3
move 2 from 4 to 2
move 5 from 8 to 3
move 25 from 5 to 2
move 3 from 3 to 6
move 1 from 1 to 3
move 3 from 6 to 7
move 1 from 4 to 2
move 1 from 5 to 8
move 2 from 4 to 9
move 1 from 8 to 1
move 20 from 2 to 7
move 10 from 7 to 1
move 1 from 1 to 7
move 4 from 7 to 8
move 5 from 5 to 4
move 4 from 8 to 6
move 1 from 1 to 3
move 5 from 7 to 4
move 2 from 1 to 5
move 4 from 9 to 1
move 3 from 2 to 5
move 5 from 5 to 1
move 1 from 9 to 1
move 11 from 1 to 3
move 1 from 6 to 2
move 7 from 3 to 5
move 11 from 3 to 7
move 1 from 2 to 6
move 7 from 7 to 8
move 1 from 9 to 1
move 2 from 3 to 1
move 1 from 5 to 3
move 4 from 1 to 6
move 4 from 6 to 3
move 9 from 4 to 5
move 2 from 8 to 2
move 4 from 6 to 9
move 3 from 2 to 4
move 1 from 8 to 6

View File

@ -1,339 +0,0 @@
use nom::{
bytes::complete::tag,
character::complete::{anychar, char, space0, space1, u8},
combinator::eof,
multi::{many0, many1, separated_list0, separated_list1},
sequence::{delimited, terminated},
IResult, Parser,
};
use std::fmt::Debug;
const INPUT: &str = include_str!("../data/day5.txt");
pub fn part1() -> String {
let (stacks, commands) = input(INPUT);
tops(run_commands(stacks, commands))
}
pub fn part2() -> String {
let (stacks, commands) = input(INPUT);
tops(run_commands_multicrate(stacks, commands))
}
fn run_commands(stacks: Stacks<char>, commands: Vec<Command>) -> Stacks<char> {
commands
.into_iter()
.fold(stacks, |stacks, command| stacks.run_command(command))
}
fn run_commands_multicrate(stacks: Stacks<char>, commands: Vec<Command>) -> Stacks<char> {
commands.into_iter().fold(stacks, |stacks, command| {
stacks.run_command_multicrate(command)
})
}
fn tops(stacks: Stacks<char>) -> String {
stacks
.0
.iter()
.map(|stack| stack.top())
.filter_map(|v| v)
.collect::<String>()
}
fn print_matrix(matrix: &Matrix<Option<char>>) {
for row in matrix.data.clone() {
for val in row {
print!(" {} ", val.unwrap_or(' '));
}
println!("");
}
}
#[derive(Clone, Debug, PartialEq)]
struct Command {
count: u8,
source: u8,
dest: u8,
}
#[derive(Clone, Debug, PartialEq)]
struct Matrix<T> {
rows: usize,
cols: usize,
data: Vec<Vec<T>>,
}
impl<T: Clone + Copy + Debug> Matrix<T> {
fn new(data: Vec<Vec<T>>) -> Self {
let rows = data.len();
let cols = data
.iter()
.fold(0, |max, row| std::cmp::max(max, row.len()));
Self { rows, cols, data }
}
fn rotate_cw(self) -> Self {
let mut data = Vec::new();
for col_idx in 0..self.cols {
let mut row = vec![];
for row_idx in 0..self.rows {
row.push(self.data[self.rows - row_idx - 1][col_idx]);
}
data.push(row);
}
Self {
rows: self.cols,
cols: self.rows,
data,
}
}
}
#[derive(Debug)]
struct Stack<T>(Vec<T>);
impl<T: Clone + Copy> Stack<T> {
fn from_option_vec(data: Vec<Option<T>>) -> Self {
Stack(data.into_iter().filter_map(|v| v).collect::<Vec<T>>())
}
fn push(&mut self, val: T) {
self.0.push(val);
}
fn pop(&mut self) -> Option<T> {
self.0.pop()
}
fn top(&self) -> Option<T> {
if self.0.len() > 0 {
Some(self.0[self.0.len() - 1])
} else {
None
}
}
}
#[derive(Debug)]
struct Stacks<T>(Vec<Stack<T>>);
impl<T: Clone + Copy> Stacks<T> {
fn run_command(mut self, cmd: Command) -> Self {
let Command {
count,
source,
dest,
} = cmd;
(0..count).for_each(|_| {
let val = self.0[(source - 1) as usize].pop().unwrap();
self.0[(dest - 1) as usize].push(val);
});
self
}
fn run_command_multicrate(mut self, cmd: Command) -> Self {
let Command {
count,
source,
dest,
} = cmd;
let mut stack = Vec::new();
(0..count).for_each(|_| {
let val = self.0[(source - 1) as usize].pop().unwrap();
stack.push(val);
});
while stack.len() > 0 {
self.0[(dest - 1) as usize].push(stack.pop().unwrap());
}
self
}
}
fn input(data: &str) -> (Stacks<char>, Vec<Command>) {
let (_, result) = parser(data).unwrap();
result
}
fn parser(input: &str) -> IResult<&str, (Stacks<char>, Vec<Command>)> {
let (input, rows) = many0(parse_crate_row)(input)?;
let (input, _) = parse_stack_numbers(input)?;
let (input, _) = space0(input)?;
let (input, _) = tag("\n")(input)?;
let (input, commands) = many1(terminated(parse_command, tag("\n").or(eof)))(input)?;
let matrix = Matrix::new(rows);
let stacks = matrix
.rotate_cw()
.data
.into_iter()
.map(|v| Stack::from_option_vec(v.clone()))
.collect::<Vec<Stack<char>>>();
Ok((input, (Stacks(stacks), commands)))
}
fn parse_command(input: &str) -> IResult<&str, Command> {
let (input, _) = tag("move ")(input)?;
let (input, count) = u8(input)?;
let (input, _) = tag(" from ")(input)?;
let (input, source) = u8(input)?;
let (input, _) = tag(" to ")(input)?;
let (input, dest) = u8(input)?;
Ok((
input,
Command {
count,
source,
dest,
},
))
}
fn parse_stack_numbers(input: &str) -> IResult<&str, usize> {
let (input, _) = space0(input)?;
let (input, stack_numbers) = separated_list1(space1, u8)(input)?;
let (input, _) = space0(input)?;
let (input, _) = tag("\n")(input)?;
Ok((input, stack_numbers.len()))
}
fn parse_crate_row(input: &str) -> IResult<&str, Vec<Option<char>>> {
let (input, cells) = terminated(separated_list0(char(' '), parse_cell), tag("\n"))(input)?;
Ok((input, cells))
}
fn parse_cell(input: &str) -> IResult<&str, Option<char>> {
parse_crate.or(parse_space).parse(input)
}
fn parse_crate(input: &str) -> IResult<&str, Option<char>> {
delimited(char('['), anychar, char(']'))
.map(|c| Some(c))
.parse(input)
}
fn parse_space(input: &str) -> IResult<&str, Option<char>> {
tag(" ").map(|_| None).parse(input)
}
#[cfg(test)]
mod test {
use super::*;
const TEST_DATA: &str = " [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";
fn with_input<F>(test: F)
where
F: Fn((Stacks<char>, Vec<Command>)) -> () + std::panic::UnwindSafe,
{
test(input(TEST_DATA));
}
#[test]
fn it_can_parse_test_data() {
with_input(|(stacks, commands)| {
assert_eq!(stacks.0[0].0, vec!['Z', 'N']);
assert_eq!(stacks.0[1].0, vec!['M', 'C', 'D']);
assert_eq!(stacks.0[2].0, vec!['P']);
assert_eq!(commands.len(), 4);
assert_eq!(
commands[0],
Command {
count: 1,
source: 2,
dest: 1
}
);
assert_eq!(
commands[3],
Command {
count: 1,
source: 1,
dest: 2
}
);
});
}
#[test]
fn it_can_follow_commands() {
with_input(|(stacks, commands)| {
let stacks = stacks.run_command(commands[0].clone());
assert_eq!(stacks.0[0].0, vec!['Z', 'N', 'D']);
assert_eq!(stacks.0[1].0, vec!['M', 'C']);
assert_eq!(stacks.0[2].0, vec!['P']);
});
with_input(|(stacks, commands)| {
let stacks = run_commands(stacks, commands);
assert_eq!(stacks.0[0].0, vec!['C']);
assert_eq!(stacks.0[1].0, vec!['M']);
assert_eq!(stacks.0[2].0, vec!['P', 'D', 'N', 'Z']);
});
}
#[test]
fn it_can_follow_multicrate_commands() {
with_input(|(stacks, commands)| {
let stacks = stacks.run_command_multicrate(commands[0].clone());
assert_eq!(stacks.0[0].0, vec!['Z', 'N', 'D']);
assert_eq!(stacks.0[1].0, vec!['M', 'C']);
assert_eq!(stacks.0[2].0, vec!['P']);
});
with_input(|(stacks, commands)| {
let stacks = run_commands_multicrate(stacks, commands);
assert_eq!(stacks.0[0].0, vec!['M']);
assert_eq!(stacks.0[1].0, vec!['C']);
assert_eq!(stacks.0[2].0, vec!['P', 'Z', 'N', 'D']);
});
}
#[test]
fn it_can_find_tops() {
with_input(|(stacks, commands)| {
let stacks = run_commands(stacks, commands);
assert_eq!(tops(stacks), "CMZ");
});
}
#[test]
fn it_can_rotate_symmetrix_matrix() {
let matrix = Matrix::new(vec![vec!['A', 'B'], vec!['C', 'D']]);
let expected = Matrix::new(vec![vec!['C', 'A'], vec!['D', 'B']]);
assert_eq!(matrix.rotate_cw(), expected);
}
#[test]
fn it_can_rotate_asymmetric_matrix() {
let matrix = Matrix::new(vec![
vec![Some('A'), Some('B'), Some('C')],
vec![Some('D'), Some('E'), Some('F')],
]);
let expected = Matrix::new(vec![
vec![Some('D'), Some('A')],
vec![Some('E'), Some('B')],
vec![Some('F'), Some('C')],
]);
print_matrix(&matrix);
print_matrix(&matrix.clone().rotate_cw());
assert_eq!(matrix.rotate_cw(), expected);
}
}

View File

@ -2,7 +2,6 @@ mod day1;
mod day2; mod day2;
mod day3; mod day3;
mod day4; mod day4;
mod day5;
fn main() { fn main() {
let day = std::env::args().skip(1).next(); let day = std::env::args().skip(1).next();
@ -16,8 +15,6 @@ fn main() {
Some("3b") => day3::part2(), Some("3b") => day3::part2(),
Some("4a") => day4::part1(), Some("4a") => day4::part1(),
Some("4b") => day4::part2(), Some("4b") => day4::part2(),
Some("5a") => day5::part1(),
Some("5b") => day5::part2(),
_ => panic!("unrecognized day"), _ => panic!("unrecognized day"),
}; };