diff --git a/2021/Cargo.toml b/2021/Cargo.toml new file mode 100644 index 0000000..1886a99 --- /dev/null +++ b/2021/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "aoc2021" +version = "0.1.0" +edition = "2021" + +[dependencies] +itertools = "0.10" +paste = "1.0" diff --git a/2021/rustfmt.toml b/2021/rustfmt.toml new file mode 100644 index 0000000..a1252c1 --- /dev/null +++ b/2021/rustfmt.toml @@ -0,0 +1,7 @@ +newline_style = "Unix" +max_width = 140 +imports_layout = "Horizontal" +merge_imports = true +struct_field_align_threshold = 25 +where_single_line = true +edition = "2021" diff --git a/2021/setup_day.sh b/2021/setup_day.sh new file mode 100755 index 0000000..aca6033 --- /dev/null +++ b/2021/setup_day.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +today=$(date +%d) +# this assumes that your puzzle input is already in your clipboard +if [ -n "$WAYLAND_DISPLAY" ]; then + wl-paste > inputs/day$today +else + xsel -b > inputs/day$today +fi +# add trailing newline if necessary +sed -i -e '$a\' inputs/day$today + +echo '#![feature(test)] +extern crate test; +use aoc2020::common::*; + +type Parsed = Vec; + +fn read_input() -> String { + read_file('$today') +} + + +fn parse_input(raw: &str) -> Parsed { + unimplemented!() +} + +fn part1(parsed: &Parsed) -> usize { + unimplemented!() +} + +fn part2(parsed: &Parsed) -> usize { + unimplemented!() +} + +fn main() { + let input = parse_input(&read_input()); + println!("Part 1: {}", part1(&input)); + println!("Part 2: {}", part2(&input)); +} + +#[cfg(test)] +mod tests { + use super::*; + use aoc2020::*; + use paste::paste; + use test::black_box; + + const TEST_INPUT: &str = ""; + + test!(part1() == 0); + test!(part2() == 0); + bench!(part1() == 0); + bench!(part2() == 0); + bench_input!(len == 0); +}' > src/bin/day$today.rs diff --git a/2021/src/common.rs b/2021/src/common.rs new file mode 100644 index 0000000..9f77058 --- /dev/null +++ b/2021/src/common.rs @@ -0,0 +1,16 @@ +use std::env; + +pub fn read_file(day: usize) -> String { + std::fs::read_to_string( + env::args() + .nth(1) + .filter(|n| n != "--bench") + .unwrap_or_else(|| format!("inputs/day{:0>2}", day)), + ) + .unwrap() +} + +#[inline] +pub fn parse_nums(l: &str) -> Vec { + l.split(',').filter_map(|n| n.parse().ok()).collect() +} diff --git a/2021/src/lib.rs b/2021/src/lib.rs new file mode 100644 index 0000000..27a56af --- /dev/null +++ b/2021/src/lib.rs @@ -0,0 +1,2 @@ +pub mod common; +pub mod teststuff; diff --git a/2021/src/teststuff.rs b/2021/src/teststuff.rs new file mode 100644 index 0000000..286fddb --- /dev/null +++ b/2021/src/teststuff.rs @@ -0,0 +1,39 @@ +#[macro_export] +macro_rules! bench { + ($part: ident ($($param: expr),*) == $expected:expr) => { + use paste::paste; + paste! { + #[bench] + fn [<$part _bench>](b: &mut test::Bencher) { + let raw = &read_input(); + let input = parse_input(&raw); + b.iter(|| assert_eq!($part(black_box(&input)$(, $param)*), $expected)); + } + } + }; +} + +#[macro_export] +macro_rules! bench_input { + ($fn:ident == $expected_len:expr) => { + #[bench] + fn bench_input_parsing(b: &mut test::Bencher) { + let raw = read_input(); + b.iter(|| assert_eq!(parse_input(black_box(&raw)).$fn(), $expected_len)); + } + }; +} + +#[macro_export] +macro_rules! test { + ($part: ident ($($param: expr),*) == $expected:expr) => { + use paste::paste; + paste! { + #[test] + fn [<$part _test>]() { + let input = parse_input(TEST_INPUT); + assert_eq!($part(&input$(, $param)*), $expected); + } + } + }; +}