[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
|
||||
# Generated by Cargo
|
||||
# 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
|
||||
|
||||
/target
|
||||
/.idea
|
||||
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