125 lines
3 KiB
Rust
125 lines
3 KiB
Rust
#![allow(dead_code, unused)]
|
|
|
|
mod util;
|
|
|
|
use std::{
|
|
fs::File,
|
|
io::{BufRead, BufReader},
|
|
path::Path,
|
|
time::Instant,
|
|
};
|
|
|
|
use once_cell::sync::Lazy;
|
|
use path_macro::path;
|
|
|
|
pub(crate) fn read_input(day: u8) -> Vec<String> {
|
|
read_input_file(path!("input" / format!("day{}.txt", day)))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub(crate) fn read_example(day: u8, part: u8) -> Vec<String> {
|
|
if part > 1 {
|
|
let p2_file = path!("example" / format!("day{day}.{part}.txt"));
|
|
if p2_file.is_file() {
|
|
return read_input_file(p2_file);
|
|
}
|
|
}
|
|
read_input_file(path!("example" / format!("day{day}.txt")))
|
|
}
|
|
|
|
fn read_input_file<P: AsRef<Path>>(path: P) -> Vec<String> {
|
|
let f = File::open(path).expect("could not read input file");
|
|
let mut input = BufReader::new(f).lines().flatten().collect::<Vec<_>>();
|
|
if let Some(last) = input.last() {
|
|
if last.is_empty() {
|
|
input.pop();
|
|
}
|
|
}
|
|
input
|
|
}
|
|
|
|
fn get_result(day: &Day, part: u8) -> String {
|
|
let input = read_input(day.n);
|
|
if part == 2 {
|
|
(day.p2)(input)
|
|
} else {
|
|
(day.p1)(input)
|
|
}
|
|
}
|
|
|
|
type SolveFn = Box<dyn Fn(Vec<String>) -> String>;
|
|
|
|
struct Day {
|
|
n: u8,
|
|
title: &'static str,
|
|
p1: SolveFn,
|
|
p2: SolveFn,
|
|
}
|
|
|
|
macro_rules! days {
|
|
( $($module:ident,)* ) => {
|
|
$(mod $module;)*
|
|
|
|
fn days() -> Vec<Day> {
|
|
vec![
|
|
$(Day {
|
|
n: $module::DAY,
|
|
title: $module::TITLE,
|
|
p1: Box::new($module::part1),
|
|
p2: Box::new($module::part2),
|
|
},)*
|
|
]
|
|
}
|
|
};
|
|
}
|
|
|
|
days! {
|
|
day1,
|
|
day2,
|
|
day3,
|
|
day4,
|
|
day5,
|
|
day6,
|
|
day7,
|
|
day8,
|
|
day9,
|
|
day10,
|
|
day11,
|
|
day12,
|
|
day13,
|
|
}
|
|
|
|
fn main() {
|
|
let mut args = std::env::args();
|
|
args.next();
|
|
let days = days();
|
|
|
|
if let Some(day) = args.next().and_then(|a| a.parse::<u8>().ok()) {
|
|
let part = args
|
|
.next()
|
|
.and_then(|arg| arg.parse::<u8>().ok().map(|p| p.clamp(1, 2)))
|
|
.unwrap_or(1);
|
|
|
|
let dobj = days.iter().find(|d| d.n == day).expect("Day not found");
|
|
let res = get_result(dobj, part);
|
|
|
|
println!("✨The result for day {}/{:?} is✨", day, part);
|
|
println!("{}", res);
|
|
} else {
|
|
println!("Advent of Code 2023 | Part one | Part two");
|
|
println!("=============================|======================|======================");
|
|
for day in days {
|
|
let title = &day.title[..day.title.len().min(20)];
|
|
|
|
let t = Instant::now();
|
|
let res_a = get_result(&day, 1);
|
|
let res_a = format!("{res_a} ({}ms)", t.elapsed().as_millis());
|
|
print!("Day {:2}: {title:20} | {res_a:20}", day.n);
|
|
|
|
let t = Instant::now();
|
|
let res_b = get_result(&day, 2);
|
|
let res_b = format!("{res_b} ({}ms)", t.elapsed().as_millis());
|
|
println!(" | {res_b:20}")
|
|
}
|
|
}
|
|
}
|