feat: prepare, solve, solve all
This commit is contained in:
		
							
								
								
									
										3
									
								
								.cargo/config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.cargo/config
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[alias]
 | 
				
			||||||
 | 
					prepare = "run --bin prepare --"
 | 
				
			||||||
 | 
					solve = "run --bin"
 | 
				
			||||||
							
								
								
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					TOKEN=secret
 | 
				
			||||||
 | 
					YEAR=2022
 | 
				
			||||||
							
								
								
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,18 @@
 | 
				
			|||||||
# Generated by Cargo
 | 
					# Generated by Cargo
 | 
				
			||||||
# will have compiled files and executables
 | 
					# will have compiled files and executables
 | 
				
			||||||
/target/
 | 
					debug/
 | 
				
			||||||
 | 
					target/
 | 
				
			||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
 | 
					 | 
				
			||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
 | 
					 | 
				
			||||||
Cargo.lock
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# These are backup files generated by rustfmt
 | 
					# These are backup files generated by rustfmt
 | 
				
			||||||
**/*.rs.bk
 | 
					**/*.rs.bk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# aoc-template
 | 
				
			||||||
 | 
					# env vars
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# downloaded inputs
 | 
				
			||||||
 | 
					src/inputs/
 | 
				
			||||||
 | 
					!src/inputs/keep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					src/test_inputs/
 | 
				
			||||||
 | 
					!src/test_inputs/keep
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# This file is automatically @generated by Cargo.
 | 
				
			||||||
 | 
					# It is not intended for manual editing.
 | 
				
			||||||
 | 
					version = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "aoc"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "pico-args",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "pico-args"
 | 
				
			||||||
 | 
					version = "0.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
 | 
				
			||||||
							
								
								
									
										11
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "aoc"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					authors = ["Matej Janežič <janezic.mj@gmail.com>"]
 | 
				
			||||||
 | 
					default-run = "aoc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					pico-args = "0.5.0"
 | 
				
			||||||
							
								
								
									
										69
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					# Advent-of-Code {YEAR}
 | 
				
			||||||
 | 
					*This is a dumbed down version of [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust/blob/main/Cargo.toml) with some extra features*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## CLI
 | 
				
			||||||
 | 
					### Prepare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					# example: `cargo prepare 1`
 | 
				
			||||||
 | 
					cargo prepare <day>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# output:
 | 
				
			||||||
 | 
					# Created module "src/bin/01.rs"
 | 
				
			||||||
 | 
					# Created empty input file "src/inputs/01.txt"
 | 
				
			||||||
 | 
					# Created empty example file "src/examples/01.txt"
 | 
				
			||||||
 | 
					# ---
 | 
				
			||||||
 | 
					# 🎄 Type `cargo solve 01` to run your solution.
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Solve
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					# example: `cargo solve 01`
 | 
				
			||||||
 | 
					cargo solve <day>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# output:
 | 
				
			||||||
 | 
					#     Running `target/debug/01`
 | 
				
			||||||
 | 
					# 🎄 Part 1 🎄
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 6 (elapsed: 37.03µs)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 🎄 Part 2 🎄
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 9 (elapsed: 33.18µs)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Displayed timings show the raw execution time of your solution without overhead (e.g. file reads). To run an optimized version for benchmarking, append the `--release` flag.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Solve all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cargo all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# output:
 | 
				
			||||||
 | 
					#     Running `target/release/aoc`
 | 
				
			||||||
 | 
					# ----------
 | 
				
			||||||
 | 
					# | Day 01 |
 | 
				
			||||||
 | 
					# ----------
 | 
				
			||||||
 | 
					# 🎄 Part 1 🎄
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 0 (elapsed: 170.00µs)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 🎄 Part 2 🎄
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 0 (elapsed: 30.00µs)
 | 
				
			||||||
 | 
					# <...other days...>
 | 
				
			||||||
 | 
					# Total: 0.20ms
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`all` is an alias for `cargo run`. To run an optimized version for benchmarking, append the `--release` flag.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Run against test inputs
 | 
				
			||||||
 | 
					run all solutions
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cargo test
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					run for a given day
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cargo test --bin <day>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										109
									
								
								src/bin/prepare.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/bin/prepare.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file contains template code.
 | 
				
			||||||
 | 
					 * There is no need to edit this file unless you want to change template functionality.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					use std::{
 | 
				
			||||||
 | 
					    fs::{File, OpenOptions},
 | 
				
			||||||
 | 
					    io::Write,
 | 
				
			||||||
 | 
					    process,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MODULE_TEMPLATE: &str = r###"pub fn part_one(input: &str) -> Option<u32> {
 | 
				
			||||||
 | 
					    None
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					pub fn part_two(input: &str) -> Option<u32> {
 | 
				
			||||||
 | 
					    None
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let input = &aoc::read_file("inputs", DAY);
 | 
				
			||||||
 | 
					    aoc::solve!(1, part_one, input);
 | 
				
			||||||
 | 
					    aoc::solve!(2, part_two, input);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_part_one() {
 | 
				
			||||||
 | 
					        let input = aoc::read_file("test_inputs", DAY);
 | 
				
			||||||
 | 
					        assert_eq!(part_one(&input), None);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_part_two() {
 | 
				
			||||||
 | 
					        let input = aoc::read_file("test_inputs", DAY);
 | 
				
			||||||
 | 
					        assert_eq!(part_two(&input), None);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"###;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_args() -> Result<u8, pico_args::Error> {
 | 
				
			||||||
 | 
					    let mut args = pico_args::Arguments::from_env();
 | 
				
			||||||
 | 
					    args.free_from_str()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			||||||
 | 
					    OpenOptions::new().write(true).create_new(true).open(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			||||||
 | 
					    OpenOptions::new().write(true).create(true).open(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let day = match parse_args() {
 | 
				
			||||||
 | 
					        Ok(day) => day,
 | 
				
			||||||
 | 
					        Err(_) => {
 | 
				
			||||||
 | 
					            eprintln!("Need to specify a day (as integer). example: `cargo prepare 7`");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let day_padded = format!("{:02}", day);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let input_path = format!("src/inputs/{}.txt", day_padded);
 | 
				
			||||||
 | 
					    let example_path = format!("src/test_inputs/{}.txt", day_padded);
 | 
				
			||||||
 | 
					    let module_path = format!("src/bin/{}.rs", day_padded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut file = match safe_create_file(&module_path) {
 | 
				
			||||||
 | 
					        Ok(file) => file,
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create module file: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match file.write_all(MODULE_TEMPLATE.replace("DAY", &day.to_string()).as_bytes()) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created module file \"{}\"", &module_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to write module contents: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match create_file(&input_path) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created empty input file \"{}\"", &input_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create input file: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match create_file(&example_path) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created empty example file \"{}\"", &example_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create example file: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("---");
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "🎄 Type `cargo solve {}` to run your solution.",
 | 
				
			||||||
 | 
					        &day_padded
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/helpers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/helpers.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										125
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file contains template code.
 | 
				
			||||||
 | 
					 * There is no need to edit this file unless you want to change template functionality.
 | 
				
			||||||
 | 
					 * Prefer `./helpers.rs` if you want to extract code from your solutions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					use std::env;
 | 
				
			||||||
 | 
					use std::fs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod helpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 {
 | 
				
			||||||
 | 
					    ($part:expr, $solver:ident, $input:expr) => {{
 | 
				
			||||||
 | 
					        use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
 | 
				
			||||||
 | 
					        use std::fmt::Display;
 | 
				
			||||||
 | 
					        use std::time::Instant;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fn print_result<T: Display>(func: impl FnOnce(&str) -> Option<T>, input: &str) {
 | 
				
			||||||
 | 
					            let timer = Instant::now();
 | 
				
			||||||
 | 
					            let result = func(input);
 | 
				
			||||||
 | 
					            let elapsed = timer.elapsed();
 | 
				
			||||||
 | 
					            match result {
 | 
				
			||||||
 | 
					                Some(result) => {
 | 
				
			||||||
 | 
					                    println!(
 | 
				
			||||||
 | 
					                        "{} {}(elapsed: {:.2?}){}",
 | 
				
			||||||
 | 
					                        result, ANSI_ITALIC, elapsed, ANSI_RESET
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                None => {
 | 
				
			||||||
 | 
					                    println!("not solved.")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        println!("🎄 {}Part {}{} 🎄", ANSI_BOLD, $part, ANSI_RESET);
 | 
				
			||||||
 | 
					        print_result($solver, $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();
 | 
				
			||||||
 | 
					            // use `contains` istd. of `ends_with`: string may contain ANSI escape sequences.
 | 
				
			||||||
 | 
					            // for possible time formats, see: https://github.com/rust-lang/rust/blob/1.64.0/library/core/src/time.rs#L1176-L1200
 | 
				
			||||||
 | 
					            if timing.contains("ns)") {
 | 
				
			||||||
 | 
					                acc // range below rounding precision.
 | 
				
			||||||
 | 
					            } else if timing.contains("µs)") {
 | 
				
			||||||
 | 
					                acc + parse_time(timing, "µs") / 1000_f64
 | 
				
			||||||
 | 
					            } else if timing.contains("ms)") {
 | 
				
			||||||
 | 
					                acc + parse_time(timing, "ms")
 | 
				
			||||||
 | 
					            } else if timing.contains("s)") {
 | 
				
			||||||
 | 
					                acc + parse_time(timing, "s") * 1000_f64
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                acc
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// copied from: https://github.com/rust-lang/rust/blob/1.64.0/library/std/src/macros.rs#L328-L333
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_parse_exec_time() {
 | 
				
			||||||
 | 
					        assert_approx_eq!(
 | 
				
			||||||
 | 
					            parse_exec_time(&format!(
 | 
				
			||||||
 | 
					                "🎄 Part 1 🎄\n0 (elapsed: 74.13ns){}\n🎄 Part 2 🎄\n0 (elapsed: 50.00ns){}",
 | 
				
			||||||
 | 
					                ANSI_RESET, ANSI_RESET
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
 | 
					            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
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file contains template code.
 | 
				
			||||||
 | 
					 * There is no need to edit this file unless you want to change template functionality.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
 | 
				
			||||||
 | 
					use std::process::Command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let total: f64 = (1..=25)
 | 
				
			||||||
 | 
					        .map(|day| {
 | 
				
			||||||
 | 
					            let day = format!("{:02}", day);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let cmd = Command::new("cargo")
 | 
				
			||||||
 | 
					                .args(["run", "--release", "--bin", &day])
 | 
				
			||||||
 | 
					                .output()
 | 
				
			||||||
 | 
					                .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            println!("----------");
 | 
				
			||||||
 | 
					            println!("{}| Day {} |{}", ANSI_BOLD, day, ANSI_RESET);
 | 
				
			||||||
 | 
					            println!("----------");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let output = String::from_utf8(cmd.stdout).unwrap();
 | 
				
			||||||
 | 
					            let is_empty = output.is_empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            println!(
 | 
				
			||||||
 | 
					                "{}",
 | 
				
			||||||
 | 
					                if is_empty {
 | 
				
			||||||
 | 
					                    "Not solved."
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    output.trim()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if is_empty {
 | 
				
			||||||
 | 
					                0_f64
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                aoc::parse_exec_time(&output)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .sum();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "{}Total:{} {}{:.2}ms{}",
 | 
				
			||||||
 | 
					        ANSI_BOLD, ANSI_RESET, ANSI_ITALIC, total, ANSI_RESET
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user