[TASK] Solved Day1 + added general architecture to run and benchmark all days
This commit is contained in:
38
src/day1.rs
Normal file
38
src/day1.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use std::cmp::Reverse;
|
||||
use crate::day_solver::{DaySolver};
|
||||
use super::util;
|
||||
|
||||
pub struct Day1 {
|
||||
elfs: Vec<Vec<u64>>
|
||||
}
|
||||
|
||||
impl Day1 {
|
||||
|
||||
pub fn create() -> Self {
|
||||
// let lines = util::read_file("input/day1_example.txt");
|
||||
let lines = util::read_file("input/day1.txt");
|
||||
|
||||
// Parse the input into a nice data structure
|
||||
let elfs = lines.split(|s| s.is_empty())
|
||||
.map(|s| s.iter().map(|i| i.parse::<u64>().unwrap()).collect::<Vec<u64>>())
|
||||
.collect();
|
||||
|
||||
return Day1 { elfs }
|
||||
}
|
||||
}
|
||||
|
||||
impl DaySolver for Day1 {
|
||||
|
||||
|
||||
fn solve_part1(&mut self) -> String {
|
||||
return self.elfs.iter().map(|e| e.iter().sum::<u64>()).max().unwrap().to_string();
|
||||
}
|
||||
|
||||
fn solve_part2(&mut self) -> String {
|
||||
let mut calories_per_elf: Vec<u64> = self.elfs.iter().map(|e| e.iter().sum()).collect();
|
||||
calories_per_elf.sort_by_key(|&c| Reverse(c));
|
||||
let part2 = calories_per_elf.iter().take(3).sum::<u64>();
|
||||
|
||||
return part2.to_string()
|
||||
}
|
||||
}
|
||||
31
src/day2.rs
Normal file
31
src/day2.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use std::cmp::Reverse;
|
||||
|
||||
use crate::day_solver::DaySolver;
|
||||
|
||||
use super::util;
|
||||
|
||||
pub struct Day2 {
|
||||
}
|
||||
|
||||
impl Day2 {
|
||||
|
||||
pub fn create() -> Self {
|
||||
// let lines = util::read_file("input/dayX_example.txt");
|
||||
let lines = util::read_file("input/dayX.txt");
|
||||
|
||||
// Put the input into the day struct
|
||||
return Day2 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DaySolver for Day2 {
|
||||
|
||||
|
||||
fn solve_part1(&mut self) -> String {
|
||||
return 0.to_string();
|
||||
}
|
||||
|
||||
fn solve_part2(&mut self) -> String {
|
||||
return 0.to_string();
|
||||
}
|
||||
}
|
||||
29
src/dayX.rs
Normal file
29
src/dayX.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use crate::day_solver::DaySolver;
|
||||
|
||||
use super::util;
|
||||
|
||||
pub struct DayX {
|
||||
}
|
||||
|
||||
impl DayX {
|
||||
|
||||
pub fn create() -> Self {
|
||||
// let lines = util::read_file("input/dayX_example.txt");
|
||||
let lines = util::read_file("input/dayX.txt");
|
||||
|
||||
// Put the input into the day struct
|
||||
return Day2 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DaySolver for DayX {
|
||||
|
||||
|
||||
fn solve_part1(&mut self) -> String {
|
||||
return 0.to_string();
|
||||
}
|
||||
|
||||
fn solve_part2(&mut self) -> String {
|
||||
return 0.to_string();
|
||||
}
|
||||
}
|
||||
6
src/day_solver.rs
Normal file
6
src/day_solver.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
pub trait DaySolver {
|
||||
// fn create() -> Self;
|
||||
fn solve_part1(&mut self) -> String;
|
||||
fn solve_part2(&mut self) -> String;
|
||||
}
|
||||
97
src/main.rs
Normal file
97
src/main.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
use std::time::Instant;
|
||||
use crate::day1::Day1;
|
||||
use crate::day2::Day2;
|
||||
use crate::day_solver::DaySolver;
|
||||
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
mod util;
|
||||
mod day1;
|
||||
mod day_solver;
|
||||
mod day2;
|
||||
|
||||
|
||||
const MAX_DAY: u8 = 1;
|
||||
const BENCHMARK_AMOUNT: u32 = 100;
|
||||
|
||||
fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
|
||||
match day {
|
||||
1 => Some(Box::new(Day1::create())),
|
||||
2 => Some(Box::new(Day2::create())),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn solve(day: u8, silent: bool) {
|
||||
|
||||
let solver = build_day_solver(day);
|
||||
|
||||
match solver {
|
||||
Some(mut s) => {
|
||||
let part1 = s.solve_part1();
|
||||
|
||||
if !silent {
|
||||
println!("Day {} Part 1: {}", day, part1);
|
||||
}
|
||||
let part2 = s.solve_part2();
|
||||
if !silent {
|
||||
println!("Day {} Part 1: {}", day, part2);
|
||||
}
|
||||
},
|
||||
None => println!("This day is not yet implemented")
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
let day_arg_idx = args.iter().position(|a| a == "-d");
|
||||
let single_day = day_arg_idx.is_some();
|
||||
let day = if single_day { args[day_arg_idx.unwrap() + 1].parse::<u8>().unwrap() } else { 0 };
|
||||
|
||||
let benchmark = args.contains(&String::from("--bench")) || args.contains(&String::from("-b"));
|
||||
|
||||
let mut bench_results: Vec<u128> = Vec::new();
|
||||
|
||||
// This is essentially the warmup for the benchmark:
|
||||
run_once(single_day, day, false, &mut bench_results);
|
||||
let first_run_time = bench_results[0];
|
||||
|
||||
if benchmark {
|
||||
// Ignore the warmup run in the rest of the benchmark:
|
||||
bench_results.clear();
|
||||
for _ in 0..BENCHMARK_AMOUNT {
|
||||
run_once(single_day, day, true,&mut bench_results);
|
||||
}
|
||||
}
|
||||
|
||||
let avg_runtime: u128 = bench_results.iter().sum::<u128>() / (bench_results.len() as u128);
|
||||
|
||||
println!("Executed {} rounds; Execution took {} μs {}", BENCHMARK_AMOUNT, avg_runtime, if benchmark { "on average" } else { "" });
|
||||
if benchmark {
|
||||
bench_results.sort();
|
||||
println!("Min: {} μs, Max: {} μs, Median: {} μs",
|
||||
bench_results[0],
|
||||
bench_results[bench_results.len() - 1],
|
||||
bench_results[bench_results.len() / 2]
|
||||
);
|
||||
println!("First time took {} μs", first_run_time);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_once(single_day: bool, day: u8, silent: bool, bench_results: &mut Vec<u128>) {
|
||||
|
||||
let now = Instant::now();
|
||||
if single_day {
|
||||
solve(day, silent);
|
||||
} else {
|
||||
solve_all(silent);
|
||||
}
|
||||
bench_results.push(now.elapsed().as_micros());
|
||||
}
|
||||
|
||||
fn solve_all(silent: bool) {
|
||||
for day in 1..(MAX_DAY + 1) {
|
||||
solve(day, silent);
|
||||
}
|
||||
}
|
||||
13
src/util.rs
Normal file
13
src/util.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use std::fs;
|
||||
|
||||
pub fn read_file(filename: &str) -> Vec<String> {
|
||||
|
||||
let contents = fs::read_to_string(filename)
|
||||
.expect("Couldn't read file!");
|
||||
|
||||
let mut res: Vec<String> = Vec::new();
|
||||
contents.lines().for_each(|l| res.push(String::from(l)));
|
||||
|
||||
res
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user