--- /dev/null
+# 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
--- /dev/null
+[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
--- /dev/null
+# 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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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)
+ }
+ }
+ }
+}