From 0a229950558de8cac0f2dffc80ff9945a2db33bd Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 26 Nov 2023 14:40:16 +0100 Subject: [PATCH 1/2] Add skeletons for all days --- .gitignore | 3 + 2023/Cargo.toml | 14 +++ 2023/benches/days.rs | 44 ++++++++ 2023/inputs/.gitkeep | 0 2023/samples/.gitkeep | 0 2023/src/common.rs | 234 ++++++++++++++++++++++++++++++++++++++++++ 2023/src/day01.rs | 7 ++ 2023/src/day02.rs | 7 ++ 2023/src/day03.rs | 7 ++ 2023/src/day04.rs | 7 ++ 2023/src/day05.rs | 7 ++ 2023/src/day06.rs | 7 ++ 2023/src/day07.rs | 7 ++ 2023/src/day08.rs | 7 ++ 2023/src/day09.rs | 7 ++ 2023/src/day10.rs | 7 ++ 2023/src/day11.rs | 7 ++ 2023/src/day12.rs | 7 ++ 2023/src/day13.rs | 7 ++ 2023/src/day14.rs | 7 ++ 2023/src/day15.rs | 7 ++ 2023/src/day16.rs | 7 ++ 2023/src/day17.rs | 7 ++ 2023/src/day18.rs | 7 ++ 2023/src/day19.rs | 7 ++ 2023/src/day20.rs | 7 ++ 2023/src/day21.rs | 7 ++ 2023/src/day22.rs | 7 ++ 2023/src/day23.rs | 7 ++ 2023/src/day24.rs | 7 ++ 2023/src/day25.rs | 3 + 2023/src/lib.rs | 91 ++++++++++++++++ 2023/src/main.rs | 61 +++++++++++ 33 files changed, 618 insertions(+) create mode 100644 2023/Cargo.toml create mode 100644 2023/benches/days.rs create mode 100644 2023/inputs/.gitkeep create mode 100644 2023/samples/.gitkeep create mode 100644 2023/src/common.rs create mode 100644 2023/src/day01.rs create mode 100644 2023/src/day02.rs create mode 100644 2023/src/day03.rs create mode 100644 2023/src/day04.rs create mode 100644 2023/src/day05.rs create mode 100644 2023/src/day06.rs create mode 100644 2023/src/day07.rs create mode 100644 2023/src/day08.rs create mode 100644 2023/src/day09.rs create mode 100644 2023/src/day10.rs create mode 100644 2023/src/day11.rs create mode 100644 2023/src/day12.rs create mode 100644 2023/src/day13.rs create mode 100644 2023/src/day14.rs create mode 100644 2023/src/day15.rs create mode 100644 2023/src/day16.rs create mode 100644 2023/src/day17.rs create mode 100644 2023/src/day18.rs create mode 100644 2023/src/day19.rs create mode 100644 2023/src/day20.rs create mode 100644 2023/src/day21.rs create mode 100644 2023/src/day22.rs create mode 100644 2023/src/day23.rs create mode 100644 2023/src/day24.rs create mode 100644 2023/src/day25.rs create mode 100644 2023/src/lib.rs create mode 100644 2023/src/main.rs diff --git a/.gitignore b/.gitignore index d2db61c..076c644 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,6 @@ target/ perf.data perf.data.old flamegraph.svg + +# Ignore saved inputs +inputs/ diff --git a/2023/Cargo.toml b/2023/Cargo.toml new file mode 100644 index 0000000..a5d649c --- /dev/null +++ b/2023/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "aoc-2023" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.75" +clap = { version = "4.4.8", features = ["derive"] } +nom = "7.1.3" + +[dev-dependencies] +criterion = "0.5.1" diff --git a/2023/benches/days.rs b/2023/benches/days.rs new file mode 100644 index 0000000..ed0120e --- /dev/null +++ b/2023/benches/days.rs @@ -0,0 +1,44 @@ +use std::fs::File; +use std::io::Read; + +use criterion::criterion_group; +use criterion::criterion_main; +use criterion::BenchmarkId; +use criterion::Criterion; + +use aoc_2023::get_implementation; + +/// Number of days we have an implementation to benchmark +const DAYS_IMPLEMENTED: u8 = 0; + +fn read_input(day: u8) -> std::io::Result> { + let input_path = format!("inputs/{day:02}.txt"); + + let mut buffer = Vec::new(); + File::open(input_path)?.read_to_end(&mut buffer)?; + + Ok(buffer) +} + +pub fn benchmark_days(c: &mut Criterion) { + for day in 1..=DAYS_IMPLEMENTED { + if let Ok(input) = read_input(day) { + let part1 = get_implementation(day, false).unwrap(); + + c.bench_with_input(BenchmarkId::new("part1", day), &input, |b, i| { + b.iter(|| part1(i)); + }); + + if day < 25 { + let part2 = get_implementation(day, true).unwrap(); + + c.bench_with_input(BenchmarkId::new("part2", day), &input, |b, i| { + b.iter(|| part2(i)); + }); + } + } + } +} + +criterion_group!(benches, benchmark_days); +criterion_main!(benches); diff --git a/2023/inputs/.gitkeep b/2023/inputs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/2023/samples/.gitkeep b/2023/samples/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/2023/src/common.rs b/2023/src/common.rs new file mode 100644 index 0000000..6fd7af5 --- /dev/null +++ b/2023/src/common.rs @@ -0,0 +1,234 @@ +//! Common helper utilities to all days + +use std::cmp::Ordering; +use std::ops::Add; +use std::ops::Div; +use std::ops::Index; +use std::ops::IndexMut; +use std::ops::Sub; + +use anyhow::Result; +use nom::combinator::map; +use nom::error::ErrorKind; +use nom::error::ParseError; +use nom::Finish; +use nom::IResult; +use nom::InputLength; +use nom::Parser; + +/// Parse input from some nom parser and return as an anyhow result +/// +/// This method exists as a convenience because nom's errors cannot otherwise be easily converted to +/// an anyhow error, and I don't want to keep track of custom error implementations here. +pub fn parse_input<'a, O>( + input: &'a [u8], + mut parser: impl Parser<&'a [u8], O, nom::error::Error<&'a [u8]>>, +) -> Result { + let (unparsed, output) = parser.parse(input).finish().map_err(|e| { + anyhow::anyhow!( + "Parser error {:?} to parse at {}", + e.code, + String::from_utf8_lossy(e.input) + ) + })?; + + if !unparsed.is_empty() { + Err(anyhow::anyhow!( + "Not all input consumed: {}", + String::from_utf8_lossy(unparsed) + )) + } else { + Ok(output) + } +} + +/// Applies a parser iteratively and reduces the results using the given function. Fails if the +/// embedded parser doesn't return at least one result. +/// +/// # Arguments +/// - `f`: the function to apply +/// - `g`: the function that combines the result o `f` with previous results +/// +/// This implementation is based on [`nom::multi::fold_many1`] with minor differences. If +/// successful, this should probably be upstreamed. +pub fn reduce_many1( + mut f: F, + mut g: impl FnMut(O, O) -> O, +) -> impl FnMut(I) -> IResult +where + I: Clone + InputLength, + E: ParseError, + F: Parser, +{ + // Cannot delegate to fold_many0 because that would make the function FnOnce rather than FnMut, + // since it would transfer ownership of the embedded parser to fold_many0. + move |i: I| { + let _i = i.clone(); + match f.parse(_i) { + Err(nom::Err::Error(_)) => { + Err(nom::Err::Error(E::from_error_kind(i, ErrorKind::Many1))) + } + Err(e) => Err(e), + Ok((i1, mut acc)) => { + let mut input = i1; + + loop { + let _input = input.clone(); + let len = input.input_len(); + match f.parse(_input) { + Err(nom::Err::Error(_)) => { + break; + } + Err(e) => return Err(e), + Ok((i, o)) => { + // infinite loop check: the parser must always consume + if i.input_len() == len { + return Err(nom::Err::Failure(E::from_error_kind( + i, + ErrorKind::Many1, + ))); + } + + acc = g(acc, o); + input = i; + } + } + } + + Ok((input, acc)) + } + } + } +} + +/// Add an index to repeated successful invocations of the embedded parser. +pub fn enumerate(f: impl Parser) -> impl FnMut(I) -> IResult { + let mut index = 0usize; + + map(f, move |v| { + let res = (index, v); + index += 1; + res + }) +} + +/// Return the minimum and maximum of two unordered variables +pub fn minmax(a: T, b: T) -> (T, T) +where + T: PartialOrd, +{ + if a < b { + (a, b) + } else { + (b, a) + } +} + +/// Some magic to get two mutable references into the same slice +pub fn get_both(slice: &mut [T], first: usize, second: usize) -> (&mut T, &mut T) { + match first.cmp(&second) { + Ordering::Greater => { + let (begin, end) = slice.split_at_mut(first); + (&mut end[0], &mut begin[second]) + } + Ordering::Less => { + let (begin, end) = slice.split_at_mut(second); + (&mut begin[first], &mut end[0]) + } + Ordering::Equal => panic!("Tried to get the same index twice {first}"), + } +} + +#[derive(Debug, Default)] +pub struct IndexSet(Vec); + +impl IndexSet { + pub fn with_capacity(capacity: usize) -> Self { + Self(Vec::with_capacity( + capacity / std::mem::size_of::() / 8, + )) + } + + fn ensure_item(&mut self, item: usize) -> &mut u32 { + if self.0.len() <= item { + self.0.resize(item + 1, 0); + } + + &mut self.0[item] + } + + #[inline] + fn index(index: usize) -> (usize, u8) { + const PER_ENTRY: usize = 8 * std::mem::size_of::(); + + (index / PER_ENTRY, (index % PER_ENTRY) as u8) + } + + pub fn insert(&mut self, index: usize) -> bool { + let (entry, pos) = Self::index(index); + + let item = self.ensure_item(entry); + let old = *item; + + *item |= 1 << pos; + + old != *item + } + + pub fn contains(&self, index: usize) -> bool { + let (entry, pos) = Self::index(index); + + self.0 + .get(entry) + .map_or(false, |&entry| (entry & (1 << pos) != 0)) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct Vec2(pub [i32; 2]); + +impl Vec2 { + pub fn l1(self) -> i32 { + self.0.into_iter().map(i32::abs).sum() + } +} + +impl Add for Vec2 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self([self[0] + rhs[0], self[1] + rhs[1]]) + } +} + +impl Sub for Vec2 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self([self[0] - rhs[0], self[1] - rhs[1]]) + } +} + +impl Div for Vec2 { + type Output = Self; + + fn div(self, rhs: i32) -> Self::Output { + Self(self.0.map(|v| v / rhs)) + } +} + +impl Index for Vec2 { + type Output = i32; + + #[inline] + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +impl IndexMut for Vec2 { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.0[index] + } +} diff --git a/2023/src/day01.rs b/2023/src/day01.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day01.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day02.rs b/2023/src/day02.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day02.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day03.rs b/2023/src/day03.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day03.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day04.rs b/2023/src/day04.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day04.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day05.rs b/2023/src/day05.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day05.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day06.rs b/2023/src/day06.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day06.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day07.rs b/2023/src/day07.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day07.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day08.rs b/2023/src/day08.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day08.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day09.rs b/2023/src/day09.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day09.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day10.rs b/2023/src/day10.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day10.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day11.rs b/2023/src/day11.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day11.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day12.rs b/2023/src/day12.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day12.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day13.rs b/2023/src/day13.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day13.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day14.rs b/2023/src/day14.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day14.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day15.rs b/2023/src/day15.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day15.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day16.rs b/2023/src/day16.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day16.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day17.rs b/2023/src/day17.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day17.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day18.rs b/2023/src/day18.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day18.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day19.rs b/2023/src/day19.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day19.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day20.rs b/2023/src/day20.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day20.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day21.rs b/2023/src/day21.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day21.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day22.rs b/2023/src/day22.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day22.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day23.rs b/2023/src/day23.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day23.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day24.rs b/2023/src/day24.rs new file mode 100644 index 0000000..7c1760f --- /dev/null +++ b/2023/src/day24.rs @@ -0,0 +1,7 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} + +pub fn part2(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/day25.rs b/2023/src/day25.rs new file mode 100644 index 0000000..0479f15 --- /dev/null +++ b/2023/src/day25.rs @@ -0,0 +1,3 @@ +pub fn part1(_input: &[u8]) -> anyhow::Result { + anyhow::bail!("Not implemented") +} diff --git a/2023/src/lib.rs b/2023/src/lib.rs new file mode 100644 index 0000000..2cc7674 --- /dev/null +++ b/2023/src/lib.rs @@ -0,0 +1,91 @@ +use anyhow::Result; + +mod common; +mod day01; +mod day02; +mod day03; +mod day04; +mod day05; +mod day06; +mod day07; +mod day08; +mod day09; +mod day10; +mod day11; +mod day12; +mod day13; +mod day14; +mod day15; +mod day16; +mod day17; +mod day18; +mod day19; +mod day20; +mod day21; +mod day22; +mod day23; +mod day24; +mod day25; + +type Solution = fn(&[u8]) -> Result; + +pub fn get_implementation(day: u8, part2: bool) -> Result { + if !part2 { + match day { + 1 => Ok(day01::part1), + 2 => Ok(day02::part1), + 3 => Ok(day03::part1), + 4 => Ok(day04::part1), + 5 => Ok(day05::part1), + 6 => Ok(day06::part1), + 7 => Ok(day07::part1), + 8 => Ok(day08::part1), + 9 => Ok(day09::part1), + 10 => Ok(day10::part1), + 11 => Ok(day11::part1), + 12 => Ok(day12::part1), + 13 => Ok(day13::part1), + 14 => Ok(day14::part1), + 15 => Ok(day15::part1), + 16 => Ok(day16::part1), + 17 => Ok(day17::part1), + 18 => Ok(day18::part1), + 19 => Ok(day19::part1), + 20 => Ok(day20::part1), + 21 => Ok(day21::part1), + 22 => Ok(day22::part1), + 23 => Ok(day23::part1), + 24 => Ok(day24::part1), + 25 => Ok(day25::part1), + _ => anyhow::bail!("Invalid day for part 1: {day}"), + } + } else { + match day { + 1 => Ok(day01::part2), + 2 => Ok(day02::part2), + 3 => Ok(day03::part2), + 4 => Ok(day04::part2), + 5 => Ok(day05::part2), + 6 => Ok(day06::part2), + 7 => Ok(day07::part2), + 8 => Ok(day08::part2), + 9 => Ok(day09::part2), + 10 => Ok(day10::part2), + 11 => Ok(day11::part2), + 12 => Ok(day12::part2), + 13 => Ok(day13::part2), + 14 => Ok(day14::part2), + 15 => Ok(day15::part2), + 16 => Ok(day16::part2), + 17 => Ok(day17::part2), + 18 => Ok(day18::part2), + 19 => Ok(day19::part2), + 20 => Ok(day20::part2), + 21 => Ok(day21::part2), + 22 => Ok(day22::part2), + 23 => Ok(day23::part2), + 24 => Ok(day24::part2), + _ => anyhow::bail!("Invalid day for part 2: {day}"), + } + } +} diff --git a/2023/src/main.rs b/2023/src/main.rs new file mode 100644 index 0000000..a986204 --- /dev/null +++ b/2023/src/main.rs @@ -0,0 +1,61 @@ +use std::fs::File; +use std::io::Read; +use std::num::NonZeroU8; +use std::path::PathBuf; +use std::time::Instant; + +use anyhow::Result; +use clap::Parser; + +use aoc_2023::get_implementation; + +/// Advent of Code 2022 runner +#[derive(Parser)] +struct Opts { + /// Which day to run + day: NonZeroU8, + + /// Print time taken + #[clap(short, long)] + time: bool, + + /// Run part 2 instead of part 1 + #[clap(short = '2', long)] + part2: bool, + + /// Read input from the given file instead of stdin + #[clap(short, long)] + input: Option, +} + +impl Opts { + fn input_data(&self) -> Result> { + let mut buffer = Vec::new(); + + if let Some(input) = &self.input { + File::open(input)?.read_to_end(&mut buffer)?; + } else { + std::io::stdin().read_to_end(&mut buffer)?; + } + + Ok(buffer) + } +} + +fn main() -> Result<()> { + let opts: Opts = Opts::parse(); + + let input = opts.input_data()?; + + let implementation = get_implementation(opts.day.get(), opts.part2)?; + + let begin = Instant::now(); + let result = implementation(&input)?; + + if opts.time { + eprintln!("Execution time: {:?}", Instant::now().duration_since(begin)); + } + + println!("{result}"); + Ok(()) +} From 4785d71e0ca1ab665c09930f5e37c23858c1a50e Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Sun, 26 Nov 2023 14:46:37 +0100 Subject: [PATCH 2/2] Update CI for 2023 No clippy warnings right now because everything is unsed anyway --- .github/workflows/2022.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/2022.yml b/.github/workflows/2022.yml index 0fc90a3..1ad8e76 100644 --- a/.github/workflows/2022.yml +++ b/.github/workflows/2022.yml @@ -1,7 +1,7 @@ on: - push -name: Advent of Code 2022 +name: Advent of Code 2023 jobs: ci: @@ -20,33 +20,33 @@ jobs: continue-on-error: ${{ matrix.experimental }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install toolchain - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true - components: rustfmt, clippy + components: rustfmt - name: Set up caching uses: Swatinem/rust-cache@v2 with: workspaces: > - 2022 -> target + 2023 -> target - name: Build binaries - working-directory: 2022 + working-directory: 2023 run: > cargo build --all-targets - name: Run tests - working-directory: 2022 + working-directory: 2023 run: > cargo test - - name: Run clippy - working-directory: 2022 + - name: Check formatting + working-directory: 2023 run: > - cargo clippy -- --deny warnings + cargo fmt --check