github.com/mnlphlp/aoc22@v0.0.0-20230330151331-c1dc4bff1b9b/aoc22_rust/src/main.rs (about) 1 use rayon::prelude::*; 2 use std::{ 3 time::{Duration, Instant}, 4 vec, 5 }; 6 7 use clap::Parser; 8 use types::Task; 9 10 mod day01; 11 mod day02; 12 mod day03; 13 mod day04; 14 mod day05; 15 mod types; 16 mod util; 17 18 type SolveFunc = dyn Fn(&str, bool, Task) -> (String, String); 19 20 const FUNCS: [&SolveFunc; 5] = [ 21 &day01::solve, 22 &day02::solve, 23 &day03::solve, 24 &day04::solve, 25 &day05::solve, 26 ]; 27 28 fn cap_length(msg: &str, length: usize) -> &str { 29 if msg.len() <= length { 30 return msg; 31 } 32 &msg[0..length] 33 } 34 35 fn calc_day( 36 day: usize, 37 result1: &mut String, 38 result2: &mut String, 39 time: &mut Duration, 40 test: bool, 41 task: Task, 42 ) { 43 if test { 44 println!("\n##################\ncalculating day {day} \n##################\n"); 45 } 46 let start = Instant::now(); 47 let input = util::read_input(day, test); 48 let (res1, res2) = FUNCS[day - 1](&input, test, task); 49 *time = Instant::now().duration_since(start); 50 *result1 = res1; 51 *result2 = res2; 52 } 53 54 #[derive(Parser)] 55 struct Args { 56 #[clap(short, long, default_value = "false")] 57 test: bool, 58 #[clap(short, long, default_value = "0")] 59 day: usize, 60 #[clap(long, default_value = "0")] 61 task: i32, 62 #[clap(short, long, default_value = "false")] 63 parallel: bool, 64 } 65 66 fn main() { 67 // parse command line arguments 68 let args: Args = Args::parse(); 69 let test = args.test; 70 let task = if args.task == 1 { 71 Task::One 72 } else if args.task == 2 { 73 Task::Two 74 } else { 75 Task::Both 76 }; 77 let day = args.day; 78 let parallel = args.parallel; 79 80 let days = if day == 0 { 81 (1..=FUNCS.len()).collect::<Vec<usize>>() 82 } else { 83 vec![day] 84 }; 85 86 println!("Calculating days: {days:?}"); 87 88 let mut results1 = vec![String::new(); days.len()]; 89 let mut results2 = vec![String::new(); days.len()]; 90 let mut times = vec![Duration::new(0, 0); days.len()]; 91 92 let start = Instant::now(); 93 if parallel { 94 run_parallel(&days, &mut results1, &mut results2, &mut times, test, task); 95 } else { 96 run_serial(&days, &mut results1, &mut results2, &mut times, test, task); 97 } 98 let overall = Instant::now().duration_since(start); 99 100 let mut results: String = "## Results:\n".into(); 101 results += "day | result 1 | result 2 | time (ms) | % overall \n"; 102 results += "--: | :-------------: | :--------------:| --------: | :--------\n"; 103 for (i, day) in days.iter().enumerate() { 104 results += &format!( 105 "{:0>3} | {: <15} | {: <15} | {: >9?} | {: >4.2} %\n", 106 day, 107 cap_length(&results1[i], 15), 108 cap_length(&results2[i], 15), 109 times[i], 110 (times[i].as_micros() as f32 / overall.as_micros() as f32) * 100f32 111 ); 112 } 113 results += &format!("\nOverall Time: {overall:?}\n"); 114 results += &format!( 115 "\nSummed Time: {:?}\n", 116 times.iter().fold(Duration::new(0, 0), |sum, x| sum + *x) 117 ); 118 119 println!("{}", results); 120 } 121 122 fn run_serial( 123 days: &[usize], 124 results1: &mut Vec<String>, 125 results2: &mut Vec<String>, 126 times: &mut Vec<Duration>, 127 test: bool, 128 task: Task, 129 ) { 130 for (i, day) in days.iter().enumerate() { 131 calc_day( 132 *day, 133 &mut results1[i], 134 &mut results2[i], 135 &mut times[i], 136 test, 137 task, 138 ); 139 } 140 } 141 142 fn run_parallel( 143 days: &[usize], 144 results1: &mut Vec<String>, 145 results2: &mut Vec<String>, 146 times: &mut Vec<Duration>, 147 test: bool, 148 task: Task, 149 ) { 150 days.par_iter() 151 .zip(results1) 152 .zip(results2) 153 .zip(times) 154 .for_each(|(((day, result1), result2), time)| { 155 calc_day(*day, result1, result2, time, test, task); 156 }); 157 }