Skip to content

Commit 8441cb2

Browse files
committed
feat: add total timing
1 parent 7430afb commit 8441cb2

File tree

4 files changed

+123
-26
lines changed

4 files changed

+123
-26
lines changed

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,25 @@ cargo run --bin <day>
8181

8282
To run an optimized version for benchmarking, use the `--release` flag or the alias `cargo rr --bin <day>`.
8383

84-
### Run all solutions
84+
### Run solutions for all days
8585

8686
```sh
8787
cargo run
88+
89+
# output:
90+
# Running `target/release/aoc`
91+
# ----------
92+
# | Day 01 |
93+
# ----------
94+
# 🎄 Part 1 🎄
95+
#
96+
# 0 (elapsed: 170.00µs)
97+
#
98+
# 🎄 Part 2 🎄
99+
#
100+
# 0 (elapsed: 30.00µs)
101+
# <...other days...>
102+
# Total: 0.20ms
88103
```
89104

90105
To run an optimized version for benchmarking, use the `--release` flag or the alias `cargo rr`.

scripts/scaffold.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ module_path="src/bin/$filename.rs";
1919
touch $module_path;
2020

2121
cat > $module_path <<EOF
22-
use aoc::{solve_day, read_file};
23-
2422
pub fn part_one(input: &str) -> u32 {
2523
0
2624
}
@@ -30,7 +28,7 @@ pub fn part_two(input: &str) -> u32 {
3028
}
3129
3230
fn main() {
33-
solve_day!(&read_file("inputs", DAYNUM), part_one, part_two)
31+
aoc::solve!(&aoc::read_file("inputs", DAYNUM), part_one, part_two)
3432
}
3533
3634
#[cfg(test)]

src/lib.rs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use std::env;
22
use std::fs;
33

4-
pub static ANSI_ITALIC: &str = "\x1b[3m";
5-
pub static ANSI_BOLD: &str = "\x1b[1m";
6-
pub static ANSI_RESET: &str = "\x1b[0m";
4+
pub const ANSI_ITALIC: &str = "\x1b[3m";
5+
pub const ANSI_BOLD: &str = "\x1b[1m";
6+
pub const ANSI_RESET: &str = "\x1b[0m";
77

88
#[macro_export]
9-
macro_rules! solve_day {
9+
macro_rules! solve {
1010
($input:expr, $part_one:ident, $part_two:ident) => {{
1111
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
1212
use std::fmt::Display;
@@ -40,3 +40,78 @@ pub fn read_file(folder: &str, day: u8) -> String {
4040
let f = fs::read_to_string(filepath);
4141
f.expect("could not open input file")
4242
}
43+
44+
fn parse_time(val: &str, postfix: &str) -> f64 {
45+
val.split(postfix).next().unwrap().parse().unwrap()
46+
}
47+
48+
pub fn parse_exec_time(output: &str) -> f64 {
49+
output.lines().fold(0_f64, |acc, l| {
50+
if !l.contains("elapsed:") {
51+
acc
52+
} else {
53+
let timing = l
54+
.split("(elapsed: ")
55+
.last()
56+
.unwrap();
57+
58+
// see [rust/library/core/src/time.rs](https://git.io/Jy1rI)
59+
if timing.ends_with("ns)") {
60+
acc // range below rounding precision.
61+
} else if timing.ends_with("µs)") {
62+
acc + parse_time(timing, "µs") / 1000_f64
63+
} else if timing.ends_with("ms)") {
64+
acc + parse_time(timing, "ms")
65+
} else if timing.ends_with("s)") {
66+
acc + parse_time(timing, "s") * 1000_f64
67+
} else {
68+
acc
69+
}
70+
}
71+
})
72+
}
73+
74+
#[cfg(test)]
75+
mod tests {
76+
use super::*;
77+
78+
/// copied from: [rust/library/std/src/macros.rs](https://git.io/Jy1r7)
79+
macro_rules! assert_approx_eq {
80+
($a:expr, $b:expr) => {{
81+
let (a, b) = (&$a, &$b);
82+
assert!(
83+
(*a - *b).abs() < 1.0e-6,
84+
"{} is not approximately equal to {}",
85+
*a,
86+
*b
87+
);
88+
}};
89+
}
90+
91+
#[test]
92+
fn test_parse_exec_time() {
93+
assert_approx_eq!(
94+
parse_exec_time(
95+
"🎄 Part 1 🎄\n0 (elapsed: 74.13ns)\n🎄 Part 2 🎄\n0 (elapsed: 50.00ns)"
96+
),
97+
0_f64
98+
);
99+
100+
assert_approx_eq!(
101+
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 755µs)\n🎄 Part 2 🎄\n0 (elapsed: 700µs)"),
102+
1.455_f64
103+
);
104+
105+
assert_approx_eq!(
106+
parse_exec_time("🎄 Part 1 🎄\n0 (elapsed: 70µs)\n🎄 Part 2 🎄\n0 (elapsed: 1.45ms)"),
107+
1.52_f64
108+
);
109+
110+
assert_approx_eq!(
111+
parse_exec_time(
112+
"🎄 Part 1 🎄\n0 (elapsed: 10.3s)\n🎄 Part 2 🎄\n0 (elapsed: 100.50ms)"
113+
),
114+
10400.50_f64
115+
);
116+
}
117+
}

src/main.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
1-
use aoc::{ANSI_BOLD, ANSI_RESET};
1+
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
22
use std::process::Command;
33

44
fn main() {
5-
(1..=25).for_each(|day| {
6-
let day = format!("{:02}", day);
5+
let total: f64 = (1..=25)
6+
.map(|day| {
7+
let day = format!("{:02}", day);
78

8-
let cmd = Command::new("cargo")
9-
.args(&["run", "--release", "--bin", &day])
10-
.output()
11-
.unwrap();
9+
let cmd = Command::new("cargo")
10+
.args(&["run", "--release", "--bin", &day])
11+
.output()
12+
.unwrap();
1213

13-
let output = String::from_utf8(cmd.stdout).unwrap();
14-
println!("----------");
15-
println!("{}| Day {} |{}", ANSI_BOLD, day, ANSI_RESET);
16-
println!("----------");
17-
println!(
18-
"{}",
19-
if !output.is_empty() {
20-
output
14+
println!("----------");
15+
println!("{}| Day {} |{}", ANSI_BOLD, day, ANSI_RESET);
16+
println!("----------");
17+
18+
let output = String::from_utf8(cmd.stdout).unwrap();
19+
let is_empty = output.is_empty();
20+
21+
println!("{}", if is_empty { "Not solved." } else { &output });
22+
23+
if is_empty {
24+
0_f64
2125
} else {
22-
"Not solved.".to_string()
26+
aoc::parse_exec_time(&output)
2327
}
24-
);
25-
});
28+
})
29+
.sum();
30+
31+
println!(
32+
"{}Total:{} {}{:.2}ms{}",
33+
ANSI_BOLD, ANSI_RESET, ANSI_ITALIC, total, ANSI_RESET
34+
);
2635
}

0 commit comments

Comments
 (0)