133 lines
3.5 KiB
Rust
133 lines
3.5 KiB
Rust
mod common;
|
|
mod days;
|
|
mod macros;
|
|
|
|
use anyhow::Result;
|
|
use common::file::read_string;
|
|
use days::{day_provider, DayTrait, ResultType};
|
|
use std::{
|
|
env,
|
|
time::{Duration, Instant},
|
|
};
|
|
use thiserror::Error;
|
|
|
|
fn output(day: usize, part: usize, result: ResultType, time: Duration) {
|
|
match result {
|
|
ResultType::Integer(value) => {
|
|
println!(
|
|
"Day {:02} part {}: {} ({})",
|
|
day,
|
|
part,
|
|
value,
|
|
time.as_secs_f64()
|
|
);
|
|
}
|
|
ResultType::String(value) => {
|
|
println!(
|
|
"Day {:02} part {}: {} ({})",
|
|
day,
|
|
part,
|
|
value,
|
|
time.as_secs_f32()
|
|
);
|
|
}
|
|
ResultType::Lines(value) => {
|
|
println!(
|
|
"Day {:02} part {}: {} ({})",
|
|
day,
|
|
part,
|
|
value[0],
|
|
time.as_secs_f32()
|
|
);
|
|
for line in &value[1..] {
|
|
println!(" {line}");
|
|
}
|
|
}
|
|
ResultType::Nothing => {}
|
|
}
|
|
}
|
|
|
|
fn run_part(day: &dyn DayTrait, is_part1: bool, lines: &str) -> Result<Duration> {
|
|
let now = Instant::now();
|
|
let result = if is_part1 {
|
|
day.part1(lines)?
|
|
} else {
|
|
day.part2(lines)?
|
|
};
|
|
|
|
if matches!(result, ResultType::Nothing) {
|
|
Ok(Duration::ZERO)
|
|
} else {
|
|
let elapsed = now.elapsed();
|
|
output(
|
|
day.get_day_number(),
|
|
if is_part1 { 1 } else { 2 },
|
|
result,
|
|
elapsed,
|
|
);
|
|
Ok(elapsed)
|
|
}
|
|
}
|
|
|
|
fn run(day: &dyn DayTrait, part1: bool, part2: bool) -> Result<Duration> {
|
|
let lines = read_string(day.get_day_number(), "input.txt")?;
|
|
let elapsed1 = if part1 {
|
|
run_part(day, true, &lines)?
|
|
} else {
|
|
Duration::ZERO
|
|
};
|
|
let elapsed2 = if part2 {
|
|
run_part(day, false, &lines)?
|
|
} else {
|
|
Duration::ZERO
|
|
};
|
|
|
|
Ok(elapsed1 + elapsed2)
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
enum ParamError {
|
|
#[error("Too many Parameters: {0}")]
|
|
TooManyParameters(usize),
|
|
|
|
#[error("Unknown Part: {0}")]
|
|
UnknownPart(usize),
|
|
}
|
|
|
|
fn run_on_parameters(params: &[String]) -> Result<()> {
|
|
match params.len() {
|
|
0 => {
|
|
let mut runtime = Duration::ZERO;
|
|
for day in day_provider::get_all_days() {
|
|
runtime += run(day.as_ref(), true, true)?;
|
|
}
|
|
println!();
|
|
println!("Runtime: {}", runtime.as_secs_f32());
|
|
}
|
|
1 => {
|
|
let mut parts = params[0].split('/');
|
|
if let Some(day_str) = parts.next() {
|
|
let day_number = day_str.parse::<usize>()?;
|
|
let day = day_provider::get_day(day_number)?;
|
|
|
|
if let Some(part_str) = parts.next() {
|
|
match part_str.parse::<usize>()? {
|
|
1 => run(day.as_ref(), true, false)?,
|
|
2 => run(day.as_ref(), false, true)?,
|
|
p => Err(ParamError::UnknownPart(p))?,
|
|
};
|
|
} else {
|
|
let runtime = run(day.as_ref(), true, true)?;
|
|
println!("Runtime: {}", runtime.as_secs_f32());
|
|
}
|
|
}
|
|
}
|
|
n => Err(ParamError::TooManyParameters(n))?,
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let params = env::args().skip(1).collect::<Vec<_>>();
|
|
run_on_parameters(¶ms)
|
|
}
|