[TASK] Solved Day1 + added general architecture to run and benchmark all days
This commit is contained in:
18
.gitignore
vendored
18
.gitignore
vendored
@@ -1,16 +1,2 @@
|
|||||||
# ---> Rust
|
/target
|
||||||
# Generated by Cargo
|
/.idea
|
||||||
# will have compiled files and executables
|
|
||||||
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
|
|
||||||
**/*.rs.bk
|
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
|
||||||
*.pdb
|
|
||||||
|
|
||||||
19
.run-bench/Run-aoc2022-bench.run.xml
Normal file
19
.run-bench/Run-aoc2022-bench.run.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run-aoc2022-bench" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --package advent-of-code-2022-rust --bin advent-of-code-2022-rust --release -- -b" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="emulateTerminal" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="NO" />
|
||||||
|
<envs />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
49
Cargo.lock
generated
Normal file
49
Cargo.lock
generated
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "advent-of-code-2022-rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "advent-of-code-2022-rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Bas Dado <bas@basdado.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
regex = "1"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
2259
input/day1.txt
Normal file
2259
input/day1.txt
Normal file
File diff suppressed because it is too large
Load Diff
14
input/day1_example.txt
Normal file
14
input/day1_example.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
1000
|
||||||
|
2000
|
||||||
|
3000
|
||||||
|
|
||||||
|
4000
|
||||||
|
|
||||||
|
5000
|
||||||
|
6000
|
||||||
|
|
||||||
|
7000
|
||||||
|
8000
|
||||||
|
9000
|
||||||
|
|
||||||
|
10000
|
||||||
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