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  }