From 2771280a7d2e5ad5c5a5c0f76e1698496ce3167b Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Thu, 1 Dec 2022 23:41:18 +0100 Subject: [PATCH] Day 1 --- .gitignore | 10 +++++++ Cargo.toml | 14 ++++++++++ README.md | 27 +++++++++++++++++++ src/common.rs | 10 +++++++ src/day01.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 192 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/common.rs create mode 100644 src/day01.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..088ba6b --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +/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 diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..bf82e1f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "advent_of_code_2022" +version = "0.1.0" +authors = ["Greg Burri "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +itertools = "0.10" +threadpool = "1.8" +regex = "1" +num = "0.4" +num_enum = "0.5" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f72c528 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# AdventOfCode2022 + +https://adventofcode.com/2022 + + +# Running tests + +Example for day 1 tests: + +~~~ +cargo test day01 -- --nocapture +~~~ + +All tests: + +~~~ +cargo test -- --nocapture +~~~ + + +# Running a day code + +~~~ +cargo run -- n +~~~ + +Where 'n' is a number from 1 to 25 diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..aa8372d --- /dev/null +++ b/src/common.rs @@ -0,0 +1,10 @@ +use std::{fs, path::Path, str::FromStr}; + +pub fn read_list_of_numbers(file: P, sep: &str) -> Vec +where + P: AsRef, + T: FromStr, + T::Err: std::fmt::Debug +{ + fs::read_to_string(file).unwrap().split(sep).map(|line| line.trim().parse::().unwrap()).collect() +} \ No newline at end of file diff --git a/src/day01.rs b/src/day01.rs new file mode 100644 index 0000000..c1875bb --- /dev/null +++ b/src/day01.rs @@ -0,0 +1,75 @@ +use std::{iter::Iterator, io::BufRead, ops::AddAssign}; + +pub fn read_calories(reader: R) -> Vec +where + R: BufRead +{ + let mut calories = vec![0i64]; + for l in reader.lines() { + let l = l.unwrap(); + let trimmed = l.trim(); + if trimmed == "" { + calories.push(0); + } else { + calories.last_mut().unwrap().add_assign(trimmed.parse::().unwrap()); + } + } + calories +} + +pub fn get_most_calories(calories: &[i64]) -> i64 { + *(calories.iter().max().unwrap()) +} + +pub fn get_sum_most_three_calories(calories: &[i64]) -> i64 { + let mut calories = Vec::from(calories); + calories.sort_by(|a, b| b.cmp(a)); + calories.iter().take(3).sum() +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1() { + let calories = + "1000 + 2000 + 3000 + + 4000 + + 5000 + 6000 + + 7000 + 8000 + 9000 + + 10000"; + assert_eq!(get_most_calories(&read_calories(calories.as_bytes())), 24000); + } + + #[test] + fn part2() { + let calories = + "1000 + 2000 + 3000 + + 4000 + + 5000 + 6000 + + 7000 + 8000 + 9000 + + 10000"; + assert_eq!(get_sum_most_three_calories(&read_calories(calories.as_bytes())), 45000); + } + +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a236cec --- /dev/null +++ b/src/main.rs @@ -0,0 +1,56 @@ +use std::{env, fs, io, time::Instant}; + +mod common; +mod day01; + +fn day01() -> String { + //let report = common::read_list_of_numbers("data/day01.input", "\n"); + let f = fs::File::open("data/day01.input").unwrap(); + let calories = day01::read_calories(std::io::BufReader::new(f)); + format!("part1: {}, part2: {}", day01::get_most_calories(&calories), day01::get_sum_most_three_calories(&calories)) +} + +fn format_micros(t: u128) -> String { + if t < 10_000 { + format!("{} μs", t) + } else if t < 10_000_000u128 { + format!("{} ms", t / 1_000u128) + } else { + format!("{} s", t / 1_000_000u128) + } +} + +fn do_day(days: &[fn() -> String], day: usize) { + let now = Instant::now(); + println!("Result of day {:02}: {} (time: {})", day, days[day - 1](), format_micros(now.elapsed().as_micros())); +} + +fn main() { + println!("https://adventofcode.com/2022"); + + let days: Vec String> = vec!( + day01, + ); + + let args: Vec = env::args().skip(1).collect(); + + // No argument -> execute all day problems. + if args.is_empty() { + let now = Instant::now(); + for i in 1 ..= days.len() { + do_day(&days, i) + } + println!("Time to execute all days: {}", format_micros(now.elapsed().as_micros())); + } else { + for arg in args { + match arg.parse::() { + Ok(day) if day >= 1 && day <= days.len() => + do_day(&days, day), + Ok(day) => + println!("Unknown day: {}", day), + Err(error) => + println!("Unable to parse day number: \"{}\", error: {}", arg, error) + } + } + } +} -- 2.45.2