use std::env; use std::fs; pub const ANSI_ITALIC: &str = "\x1b[3m"; pub const ANSI_BOLD: &str = "\x1b[1m"; pub const ANSI_RESET: &str = "\x1b[0m"; #[macro_export] macro_rules! solve { ($input:expr, $part_one:ident, $part_two:ident) => {{ use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET}; use std::fmt::Display; use std::time::Instant; fn print_result(func: impl FnOnce(&str) -> T, input: &str) { let timer = Instant::now(); let result = func(input); let time = timer.elapsed(); println!( "{} {}(elapsed: {:.2?}){}", result, ANSI_ITALIC, time, ANSI_RESET ); } println!("๐ŸŽ„ {}Part 1{} ๐ŸŽ„", ANSI_BOLD, ANSI_RESET); println!(""); print_result($part_one, $input); println!(""); println!("๐ŸŽ„ {}Part 2{} ๐ŸŽ„", ANSI_BOLD, ANSI_RESET); println!(""); print_result($part_two, $input); }}; } pub fn read_file(folder: &str, day: u8) -> String { let cwd = env::current_dir().unwrap(); let filepath = cwd.join("src").join(folder).join(format!("{:02}.txt", day)); let f = fs::read_to_string(filepath); f.expect("could not open input file") } fn parse_time(val: &str, postfix: &str) -> f64 { val.split(postfix).next().unwrap().parse().unwrap() } pub fn parse_exec_time(output: &str) -> f64 { output.lines().fold(0_f64, |acc, l| { if !l.contains("elapsed:") { acc } else { let timing = l .split("(elapsed: ") .last() .unwrap(); // see [rust/library/core/src/time.rs](https://git.io/Jy1rI) if timing.ends_with("ns)") { acc // range below rounding precision. } else if timing.ends_with("ยตs)") { acc + parse_time(timing, "ยตs") / 1000_f64 } else if timing.ends_with("ms)") { acc + parse_time(timing, "ms") } else if timing.ends_with("s)") { acc + parse_time(timing, "s") * 1000_f64 } else { acc } } }) } #[cfg(test)] mod tests { use super::*; /// copied from: [rust/library/std/src/macros.rs](https://git.io/Jy1r7) macro_rules! assert_approx_eq { ($a:expr, $b:expr) => {{ let (a, b) = (&$a, &$b); assert!( (*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b ); }}; } #[test] fn test_parse_exec_time() { assert_approx_eq!( parse_exec_time( "๐ŸŽ„ Part 1 ๐ŸŽ„\n0 (elapsed: 74.13ns)\n๐ŸŽ„ Part 2 ๐ŸŽ„\n0 (elapsed: 50.00ns)" ), 0_f64 ); assert_approx_eq!( parse_exec_time("๐ŸŽ„ Part 1 ๐ŸŽ„\n0 (elapsed: 755ยตs)\n๐ŸŽ„ Part 2 ๐ŸŽ„\n0 (elapsed: 700ยตs)"), 1.455_f64 ); assert_approx_eq!( parse_exec_time("๐ŸŽ„ Part 1 ๐ŸŽ„\n0 (elapsed: 70ยตs)\n๐ŸŽ„ Part 2 ๐ŸŽ„\n0 (elapsed: 1.45ms)"), 1.52_f64 ); assert_approx_eq!( parse_exec_time( "๐ŸŽ„ Part 1 ๐ŸŽ„\n0 (elapsed: 10.3s)\n๐ŸŽ„ Part 2 ๐ŸŽ„\n0 (elapsed: 100.50ms)" ), 10400.50_f64 ); } }