Day 1
authorGreg Burri <greg.burri@gmail.com>
Thu, 1 Dec 2022 22:41:18 +0000 (23:41 +0100)
committerGreg Burri <greg.burri@gmail.com>
Thu, 1 Dec 2022 22:41:18 +0000 (23:41 +0100)
.gitignore [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
README.md [new file with mode: 0644]
src/common.rs [new file with mode: 0644]
src/day01.rs [new file with mode: 0644]
src/main.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..088ba6b
--- /dev/null
@@ -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 (file)
index 0000000..bf82e1f
--- /dev/null
@@ -0,0 +1,14 @@
+[package]
+name = "advent_of_code_2022"
+version = "0.1.0"
+authors = ["Greg Burri <greg.burri@gmail.com>"]
+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 (file)
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 (file)
index 0000000..aa8372d
--- /dev/null
@@ -0,0 +1,10 @@
+use std::{fs, path::Path, str::FromStr};
+
+pub fn read_list_of_numbers<P, T>(file: P, sep: &str) -> Vec<T>
+where
+    P: AsRef<Path>,
+    T: FromStr,
+    T::Err: std::fmt::Debug
+{
+    fs::read_to_string(file).unwrap().split(sep).map(|line| line.trim().parse::<T>().unwrap()).collect()
+}
\ No newline at end of file
diff --git a/src/day01.rs b/src/day01.rs
new file mode 100644 (file)
index 0000000..c1875bb
--- /dev/null
@@ -0,0 +1,75 @@
+use std::{iter::Iterator, io::BufRead, ops::AddAssign};
+
+pub fn read_calories<R>(reader: R) -> Vec<i64>
+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::<i64>().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 (file)
index 0000000..a236cec
--- /dev/null
@@ -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<fn() -> String> = vec!(
+        day01,
+    );
+
+    let args: Vec<String> = 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::<usize>() {
+                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)
+            }
+        }
+    }
+}