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 { 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 { 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::()?; let day = day_provider::get_day(day_number)?; if let Some(part_str) = parts.next() { match part_str.parse::()? { 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::>(); run_on_parameters(¶ms) }