diff options
author | Jesse Luehrs <doy@tozt.net> | 2022-12-11 21:59:21 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2022-12-11 22:16:30 -0500 |
commit | e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06 (patch) | |
tree | 93e418011c45cab8d4070d3d33b377a9364f4a27 | |
parent | 179467096141b7e8f67d63b89fd21e779a564fe6 (diff) | |
download | advent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.tar.gz advent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.zip |
refactor
-rwxr-xr-x | bin/stub-code | 9 | ||||
-rw-r--r-- | src/2020/mod.rs | 47 | ||||
-rw-r--r-- | src/2021/mod.rs | 111 | ||||
-rw-r--r-- | src/2022/mod.rs | 55 | ||||
-rw-r--r-- | src/bin/2020/day1.rs (renamed from src/2020/1/mod.rs) | 10 | ||||
-rw-r--r-- | src/bin/2020/day2.rs (renamed from src/2020/2/mod.rs) | 22 | ||||
-rw-r--r-- | src/bin/2020/day3.rs (renamed from src/2020/3/mod.rs) | 10 | ||||
-rw-r--r-- | src/bin/2020/day4.rs (renamed from src/2020/4/mod.rs) | 8 | ||||
-rw-r--r-- | src/bin/2020/day5.rs (renamed from src/2020/5/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2020/day6.rs (renamed from src/2020/6/mod.rs) | 16 | ||||
-rw-r--r-- | src/bin/2020/day7.rs (renamed from src/2020/7/mod.rs) | 14 | ||||
-rw-r--r-- | src/bin/2020/day8.rs (renamed from src/2020/8/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2020/day9.rs (renamed from src/2020/9/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2020/main.rs | 42 | ||||
-rw-r--r-- | src/bin/2021/day1.rs (renamed from src/2021/1/mod.rs) | 14 | ||||
-rw-r--r-- | src/bin/2021/day10.rs (renamed from src/2021/10/mod.rs) | 8 | ||||
-rw-r--r-- | src/bin/2021/day11.rs (renamed from src/2021/11/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2021/day12.rs (renamed from src/2021/12/mod.rs) | 15 | ||||
-rw-r--r-- | src/bin/2021/day13.rs (renamed from src/2021/13/mod.rs) | 16 | ||||
-rw-r--r-- | src/bin/2021/day14.rs (renamed from src/2021/14/mod.rs) | 8 | ||||
-rw-r--r-- | src/bin/2021/day15.rs (renamed from src/2021/15/mod.rs) | 16 | ||||
-rw-r--r-- | src/bin/2021/day16.rs (renamed from src/2021/16/mod.rs) | 20 | ||||
-rw-r--r-- | src/bin/2021/day17.rs (renamed from src/2021/17/mod.rs) | 6 | ||||
-rw-r--r-- | src/bin/2021/day18.rs (renamed from src/2021/18/mod.rs) | 20 | ||||
-rw-r--r-- | src/bin/2021/day19.rs (renamed from src/2021/19/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2021/day2.rs (renamed from src/2021/2/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2021/day20.rs (renamed from src/2021/20/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2021/day21.rs (renamed from src/2021/21/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2021/day22.rs (renamed from src/2021/22/mod.rs) | 6 | ||||
-rw-r--r-- | src/bin/2021/day23.rs (renamed from src/2021/23/mod.rs) | 18 | ||||
-rw-r--r-- | src/bin/2021/day24.rs (renamed from src/2021/24/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2021/day25.rs (renamed from src/2021/25/mod.rs) | 6 | ||||
-rw-r--r-- | src/bin/2021/day3.rs (renamed from src/2021/3/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2021/day4.rs (renamed from src/2021/4/mod.rs) | 22 | ||||
-rw-r--r-- | src/bin/2021/day5.rs (renamed from src/2021/5/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2021/day6.rs (renamed from src/2021/6/mod.rs) | 14 | ||||
-rw-r--r-- | src/bin/2021/day7.rs (renamed from src/2021/7/mod.rs) | 14 | ||||
-rw-r--r-- | src/bin/2021/day8.rs (renamed from src/2021/8/mod.rs) | 18 | ||||
-rw-r--r-- | src/bin/2021/day9.rs (renamed from src/2021/9/mod.rs) | 10 | ||||
-rw-r--r-- | src/bin/2021/main.rs | 74 | ||||
-rw-r--r-- | src/bin/2022/day1.rs (renamed from src/2022/1/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2022/day10.rs (renamed from src/2022/10/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2022/day11.rs (renamed from src/2022/11/mod.rs) | 52 | ||||
-rw-r--r-- | src/bin/2022/day2.rs (renamed from src/2022/2/mod.rs) | 12 | ||||
-rw-r--r-- | src/bin/2022/day3.rs (renamed from src/2022/3/mod.rs) | 15 | ||||
-rw-r--r-- | src/bin/2022/day4.rs (renamed from src/2022/4/mod.rs) | 20 | ||||
-rw-r--r-- | src/bin/2022/day5.rs (renamed from src/2022/5/mod.rs) | 4 | ||||
-rw-r--r-- | src/bin/2022/day6.rs (renamed from src/2022/6/mod.rs) | 10 | ||||
-rw-r--r-- | src/bin/2022/day7.rs (renamed from src/2022/7/mod.rs) | 16 | ||||
-rw-r--r-- | src/bin/2022/day8.rs (renamed from src/2022/8/mod.rs) | 10 | ||||
-rw-r--r-- | src/bin/2022/day9.rs (renamed from src/2022/9/mod.rs) | 16 | ||||
-rw-r--r-- | src/bin/2022/main.rs | 46 | ||||
-rw-r--r-- | src/graph.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 18 | ||||
-rw-r--r-- | src/main.rs | 55 | ||||
-rw-r--r-- | src/opt.rs | 20 | ||||
-rw-r--r-- | src/parse.rs | 31 | ||||
-rw-r--r-- | src/prelude.rs | 2 | ||||
-rw-r--r-- | src/regex.rs | 1 |
59 files changed, 520 insertions, 577 deletions
diff --git a/bin/stub-code b/bin/stub-code index 1212e33..6e91995 100755 --- a/bin/stub-code +++ b/bin/stub-code @@ -4,12 +4,11 @@ set -eu day=${1:-$(date +%-d)} year=${2:-$(date +%Y)} -mkdir -p src/"$year"/"$day" -cat >src/"$year"/"$day"/mod.rs <<EOF +cat >src/bin/"$year"/day"$day".rs <<EOF #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Todo; @@ -38,5 +37,5 @@ fn test() { } EOF -perl -pi -E"\$seen_mod = 1 if /mod day$day/; if (!\$seen_mod && /NEXT MOD/) { say '#[path = \"$day/mod.rs\"]'; say 'mod day$day;'; }" src/"$year"/mod.rs -perl -pi -E"\$seen_part = 1 if /day$day::part/; if (!\$seen_part && /NEXT PART/) { say ' ($day, 1) => day$day::part1(day$day::parse(parse::data($year, $day)?)?),'; say ' ($day, 2) => day$day::part2(day$day::parse(parse::data($year, $day)?)?),'; }" src/"$year"/mod.rs +perl -pi -E"\$seen_mod = 1 if /mod day$day;/; if (!\$seen_mod && /NEXT MOD/) { say 'mod day$day;'; }" src/bin/"$year"/main.rs +perl -pi -E"\$seen_part = 1 if /day!.*day$day\)/; if (!\$seen_part && /NEXT PART/) { say ' $day => advent_of_code::day!($year, opt.day, opt.puzzle, day$day),'; }" src/bin/"$year"/main.rs diff --git a/src/2020/mod.rs b/src/2020/mod.rs deleted file mode 100644 index 83e6a6e..0000000 --- a/src/2020/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::prelude::*; - -#[path = "1/mod.rs"] -mod day1; -#[path = "2/mod.rs"] -mod day2; -#[path = "3/mod.rs"] -mod day3; -#[path = "4/mod.rs"] -mod day4; -#[path = "5/mod.rs"] -mod day5; -#[path = "6/mod.rs"] -mod day6; -#[path = "7/mod.rs"] -mod day7; -#[path = "8/mod.rs"] -mod day8; -#[path = "9/mod.rs"] -mod day9; -// NEXT MOD - -pub fn run(day: u8, puzzle: u8) -> Result<i64> { - #[allow(clippy::match_single_binding)] - match (day, puzzle) { - (1, 1) => day1::part1(day1::parse(parse::data(2020, 1)?)?), - (1, 2) => day1::part2(day1::parse(parse::data(2020, 1)?)?), - (2, 1) => day2::part1(day2::parse(parse::data(2020, 2)?)?), - (2, 2) => day2::part2(day2::parse(parse::data(2020, 2)?)?), - (3, 1) => day3::part1(day3::parse(parse::data(2020, 3)?)?), - (3, 2) => day3::part2(day3::parse(parse::data(2020, 3)?)?), - (4, 1) => day4::part1(day4::parse(parse::data(2020, 4)?)?), - (4, 2) => day4::part2(day4::parse(parse::data(2020, 4)?)?), - (5, 1) => day5::part1(day5::parse(parse::data(2020, 5)?)?), - (5, 2) => day5::part2(day5::parse(parse::data(2020, 5)?)?), - (6, 1) => day6::part1(day6::parse(parse::data(2020, 6)?)?), - (6, 2) => day6::part2(day6::parse(parse::data(2020, 6)?)?), - (7, 1) => day7::part1(day7::parse(parse::data(2020, 7)?)?), - (7, 2) => day7::part2(day7::parse(parse::data(2020, 7)?)?), - (8, 1) => day8::part1(day8::parse(parse::data(2020, 8)?)?), - (8, 2) => day8::part2(day8::parse(parse::data(2020, 8)?)?), - (9, 1) => day9::part1(day9::parse(parse::data(2020, 9)?)?), - (9, 2) => day9::part2(day9::parse(parse::data(2020, 9)?)?), - // NEXT PART - _ => Err(anyhow!("unknown puzzle {}-{}", day, puzzle)), - } -} diff --git a/src/2021/mod.rs b/src/2021/mod.rs deleted file mode 100644 index a1e4c09..0000000 --- a/src/2021/mod.rs +++ /dev/null @@ -1,111 +0,0 @@ -use crate::prelude::*; - -#[path = "1/mod.rs"] -mod day1; -#[path = "10/mod.rs"] -mod day10; -#[path = "11/mod.rs"] -mod day11; -#[path = "12/mod.rs"] -mod day12; -#[path = "13/mod.rs"] -mod day13; -#[path = "14/mod.rs"] -mod day14; -#[path = "15/mod.rs"] -mod day15; -#[path = "16/mod.rs"] -mod day16; -#[path = "17/mod.rs"] -mod day17; -#[path = "18/mod.rs"] -mod day18; -#[path = "19/mod.rs"] -mod day19; -#[path = "2/mod.rs"] -mod day2; -#[path = "20/mod.rs"] -mod day20; -#[path = "21/mod.rs"] -mod day21; -#[path = "22/mod.rs"] -mod day22; -#[path = "23/mod.rs"] -mod day23; -#[path = "24/mod.rs"] -mod day24; -#[path = "25/mod.rs"] -mod day25; -#[path = "3/mod.rs"] -mod day3; -#[path = "4/mod.rs"] -mod day4; -#[path = "5/mod.rs"] -mod day5; -#[path = "6/mod.rs"] -mod day6; -#[path = "7/mod.rs"] -mod day7; -#[path = "8/mod.rs"] -mod day8; -#[path = "9/mod.rs"] -mod day9; -// NEXT MOD - -pub fn run(day: u8, puzzle: u8) -> Result<i64> { - #[allow(clippy::match_single_binding)] - match (day, puzzle) { - (1, 1) => day1::part1(day1::parse(parse::data(2021, 1)?)?), - (1, 2) => day1::part2(day1::parse(parse::data(2021, 1)?)?), - (2, 1) => day2::part1(day2::parse(parse::data(2021, 2)?)?), - (2, 2) => day2::part2(day2::parse(parse::data(2021, 2)?)?), - (3, 1) => day3::part1(day3::parse(parse::data(2021, 3)?)?), - (3, 2) => day3::part2(day3::parse(parse::data(2021, 3)?)?), - (4, 1) => day4::part1(day4::parse(parse::data(2021, 4)?)?), - (4, 2) => day4::part2(day4::parse(parse::data(2021, 4)?)?), - (5, 1) => day5::part1(day5::parse(parse::data(2021, 5)?)?), - (5, 2) => day5::part2(day5::parse(parse::data(2021, 5)?)?), - (6, 1) => day6::part1(day6::parse(parse::data(2021, 6)?)?), - (6, 2) => day6::part2(day6::parse(parse::data(2021, 6)?)?), - (7, 1) => day7::part1(day7::parse(parse::data(2021, 7)?)?), - (7, 2) => day7::part2(day7::parse(parse::data(2021, 7)?)?), - (8, 1) => day8::part1(day8::parse(parse::data(2021, 8)?)?), - (8, 2) => day8::part2(day8::parse(parse::data(2021, 8)?)?), - (9, 1) => day9::part1(day9::parse(parse::data(2021, 9)?)?), - (9, 2) => day9::part2(day9::parse(parse::data(2021, 9)?)?), - (10, 1) => day10::part1(day10::parse(parse::data(2021, 10)?)?), - (10, 2) => day10::part2(day10::parse(parse::data(2021, 10)?)?), - (11, 1) => day11::part1(day11::parse(parse::data(2021, 11)?)?), - (11, 2) => day11::part2(day11::parse(parse::data(2021, 11)?)?), - (12, 1) => day12::part1(day12::parse(parse::data(2021, 12)?)?), - (12, 2) => day12::part2(day12::parse(parse::data(2021, 12)?)?), - (13, 1) => day13::part1(day13::parse(parse::data(2021, 13)?)?), - (13, 2) => day13::part2(day13::parse(parse::data(2021, 13)?)?), - (14, 1) => day14::part1(day14::parse(parse::data(2021, 14)?)?), - (14, 2) => day14::part2(day14::parse(parse::data(2021, 14)?)?), - (15, 1) => day15::part1(day15::parse(parse::data(2021, 15)?)?), - (15, 2) => day15::part2(day15::parse(parse::data(2021, 15)?)?), - (16, 1) => day16::part1(day16::parse(parse::data(2021, 16)?)?), - (16, 2) => day16::part2(day16::parse(parse::data(2021, 16)?)?), - (17, 1) => day17::part1(day17::parse(parse::data(2021, 17)?)?), - (17, 2) => day17::part2(day17::parse(parse::data(2021, 17)?)?), - (18, 1) => day18::part1(day18::parse(parse::data(2021, 18)?)?), - (18, 2) => day18::part2(day18::parse(parse::data(2021, 18)?)?), - (19, 1) => day19::part1(day19::parse(parse::data(2021, 19)?)?), - (19, 2) => day19::part2(day19::parse(parse::data(2021, 19)?)?), - (20, 1) => day20::part1(day20::parse(parse::data(2021, 20)?)?), - (20, 2) => day20::part2(day20::parse(parse::data(2021, 20)?)?), - (21, 1) => day21::part1(day21::parse(parse::data(2021, 21)?)?), - (21, 2) => day21::part2(day21::parse(parse::data(2021, 21)?)?), - (22, 1) => day22::part1(day22::parse(parse::data(2021, 22)?)?), - (22, 2) => day22::part2(day22::parse(parse::data(2021, 22)?)?), - (23, 1) => day23::part1(day23::parse(parse::data(2021, 23)?)?), - (23, 2) => day23::part2(day23::parse(parse::data(2021, 23)?)?), - (24, 1) => day24::part1(day24::parse(parse::data(2021, 24)?)?), - (24, 2) => day24::part2(day24::parse(parse::data(2021, 24)?)?), - (25, 1) => day25::part1(day25::parse(parse::data(2021, 25)?)?), - (25, 2) => day25::part2(day25::parse(parse::data(2021, 25)?)?), - // NEXT PART - _ => Err(anyhow!("unknown puzzle {}-{}", day, puzzle)), - } -} diff --git a/src/2022/mod.rs b/src/2022/mod.rs deleted file mode 100644 index 5c836a1..0000000 --- a/src/2022/mod.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::prelude::*; - -#[path = "1/mod.rs"] -mod day1; -#[path = "2/mod.rs"] -mod day2; -#[path = "3/mod.rs"] -mod day3; -#[path = "4/mod.rs"] -mod day4; -#[path = "5/mod.rs"] -mod day5; -#[path = "6/mod.rs"] -mod day6; -#[path = "7/mod.rs"] -mod day7; -#[path = "8/mod.rs"] -mod day8; -#[path = "9/mod.rs"] -mod day9; -#[path = "10/mod.rs"] -mod day10; -#[path = "11/mod.rs"] -mod day11; -// NEXT MOD - -pub fn run(day: u8, puzzle: u8) -> Result<i64> { - #[allow(clippy::match_single_binding)] - match (day, puzzle) { - (1, 1) => day1::part1(day1::parse(parse::data(2022, 1)?)?), - (1, 2) => day1::part2(day1::parse(parse::data(2022, 1)?)?), - (2, 1) => day2::part1(day2::parse(parse::data(2022, 2)?)?), - (2, 2) => day2::part2(day2::parse(parse::data(2022, 2)?)?), - (3, 1) => day3::part1(day3::parse(parse::data(2022, 3)?)?), - (3, 2) => day3::part2(day3::parse(parse::data(2022, 3)?)?), - (4, 1) => day4::part1(day4::parse(parse::data(2022, 4)?)?), - (4, 2) => day4::part2(day4::parse(parse::data(2022, 4)?)?), - (5, 1) => day5::part1(day5::parse(parse::data(2022, 5)?)?), - (5, 2) => day5::part2(day5::parse(parse::data(2022, 5)?)?), - (6, 1) => day6::part1(day6::parse(parse::data(2022, 6)?)?), - (6, 2) => day6::part2(day6::parse(parse::data(2022, 6)?)?), - (7, 1) => day7::part1(day7::parse(parse::data(2022, 7)?)?), - (7, 2) => day7::part2(day7::parse(parse::data(2022, 7)?)?), - (8, 1) => day8::part1(day8::parse(parse::data(2022, 8)?)?), - (8, 2) => day8::part2(day8::parse(parse::data(2022, 8)?)?), - (9, 1) => day9::part1(day9::parse(parse::data(2022, 9)?)?), - (9, 2) => day9::part2(day9::parse(parse::data(2022, 9)?)?), - (10, 1) => day10::part1(day10::parse(parse::data(2022, 10)?)?), - (10, 2) => day10::part2(day10::parse(parse::data(2022, 10)?)?), - (11, 1) => day11::part1(day11::parse(parse::data(2022, 11)?)?), - (11, 2) => day11::part2(day11::parse(parse::data(2022, 11)?)?), - // NEXT PART - _ => Err(anyhow!("unknown puzzle {}-{}", day, puzzle)), - } -} diff --git a/src/2020/1/mod.rs b/src/bin/2020/day1.rs index 1ed3824..8e582d8 100644 --- a/src/2020/1/mod.rs +++ b/src/bin/2020/day1.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -pub fn parse(fh: File) -> Result<Vec<i64>> { - Ok(parse::ints(parse::lines(fh)).collect()) +pub fn parse(fh: File) -> Result<Vec<u64>> { + Ok(parse::lines(fh).collect()) } -pub fn part1(ints: Vec<i64>) -> Result<i64> { +pub fn part1(ints: Vec<u64>) -> Result<u64> { for i in &ints { for j in &ints { if i + j == 2020 { @@ -15,7 +15,7 @@ pub fn part1(ints: Vec<i64>) -> Result<i64> { Err(anyhow!("no numbers summing to 2020 found")) } -pub fn part2(ints: Vec<i64>) -> Result<i64> { +pub fn part2(ints: Vec<u64>) -> Result<u64> { for i in &ints { for j in &ints { for k in &ints { diff --git a/src/2020/2/mod.rs b/src/bin/2020/day2.rs index a2ff9df..9d25860 100644 --- a/src/2020/2/mod.rs +++ b/src/bin/2020/day2.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Line { c: char, @@ -7,8 +7,10 @@ pub struct Line { password: String, } -impl Line { - fn parse(line: &str) -> Result<Self> { +impl std::str::FromStr for Line { + type Err = anyhow::Error; + + fn from_str(line: &str) -> Result<Self, Self::Err> { let captures = regex_captures!(r"^([0-9]+)-([0-9]+) (.): (.*)$", line) .context("line failed to match regex")?; @@ -38,7 +40,9 @@ impl Line { password, }) } +} +impl Line { fn valid_part_1(&self) -> bool { let count = self.password.chars().filter(|c| *c == self.c).count(); count >= self.n1 && count <= self.n2 @@ -51,17 +55,15 @@ impl Line { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Line>> { - Ok(parse::lines(fh).map(|line| Line::parse(&line).unwrap())) + Ok(parse::lines(fh)) } -pub fn part1(lines: impl Iterator<Item = Line>) -> Result<i64> { - let count = lines.filter(|l| l.valid_part_1()).count(); - Ok(count.try_into()?) +pub fn part1(lines: impl Iterator<Item = Line>) -> Result<usize> { + Ok(lines.filter(|l| l.valid_part_1()).count()) } -pub fn part2(lines: impl Iterator<Item = Line>) -> Result<i64> { - let count = lines.filter(|l| l.valid_part_2()).count(); - Ok(count.try_into()?) +pub fn part2(lines: impl Iterator<Item = Line>) -> Result<usize> { + Ok(lines.filter(|l| l.valid_part_2()).count()) } #[test] diff --git a/src/2020/3/mod.rs b/src/bin/2020/day3.rs index 29e20d2..a2314ee 100644 --- a/src/2020/3/mod.rs +++ b/src/bin/2020/day3.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Map { grid: Grid<bool>, @@ -22,7 +22,7 @@ impl Map { &self, row_incr: usize, col_incr: usize, - ) -> Result<i64> { + ) -> Result<u64> { let mut trees = 0; for r in 0..self.rows() / row_incr { let row = r * row_incr; @@ -36,14 +36,14 @@ impl Map { } pub fn parse(fh: File) -> Result<Map> { - Ok(Map::new(parse::bool_grid(parse::lines(fh), b'#', b'.'))) + Ok(Map::new(parse::bool_grid(parse::raw_lines(fh), b'#', b'.'))) } -pub fn part1(map: Map) -> Result<i64> { +pub fn part1(map: Map) -> Result<u64> { map.trees_for_slope(1, 3) } -pub fn part2(map: Map) -> Result<i64> { +pub fn part2(map: Map) -> Result<u64> { Ok(map.trees_for_slope(1, 1)? * map.trees_for_slope(1, 3)? * map.trees_for_slope(1, 5)? diff --git a/src/2020/4/mod.rs b/src/bin/2020/day4.rs index b198c31..aed67cb 100644 --- a/src/2020/4/mod.rs +++ b/src/bin/2020/day4.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; const REQUIRED_KEYS: &[&str] = &["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]; @@ -6,7 +6,7 @@ const REQUIRED_KEYS: &[&str] = pub fn parse(fh: File) -> Result<Vec<HashMap<String, String>>> { let mut res = vec![]; let mut cur = HashMap::new(); - let mut lines = parse::lines(fh).peekable(); + let mut lines = parse::raw_lines(fh).peekable(); while lines.peek().is_some() { for line in parse::chunk(&mut lines) { for field in line.split(' ') { @@ -29,7 +29,7 @@ pub fn parse(fh: File) -> Result<Vec<HashMap<String, String>>> { Ok(res) } -pub fn part1(passports: Vec<HashMap<String, String>>) -> Result<i64> { +pub fn part1(passports: Vec<HashMap<String, String>>) -> Result<u64> { let mut valid = 0; for passport in passports { let mut cur_valid = true; @@ -46,7 +46,7 @@ pub fn part1(passports: Vec<HashMap<String, String>>) -> Result<i64> { Ok(valid) } -pub fn part2(passports: Vec<HashMap<String, String>>) -> Result<i64> { +pub fn part2(passports: Vec<HashMap<String, String>>) -> Result<u64> { let mut valid = 0; for passport in passports { let mut cur_valid = true; diff --git a/src/2020/5/mod.rs b/src/bin/2020/day5.rs index 1f57f4f..abfd400 100644 --- a/src/2020/5/mod.rs +++ b/src/bin/2020/day5.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -pub fn parse(fh: File) -> Result<impl Iterator<Item = i64>> { - Ok(parse::lines(fh).map(|line| seat_id(&line).unwrap())) +pub fn parse(fh: File) -> Result<impl Iterator<Item = u64>> { + Ok(parse::raw_lines(fh).map(|line| seat_id(&line).unwrap())) } -pub fn part1(ids: impl Iterator<Item = i64>) -> Result<i64> { +pub fn part1(ids: impl Iterator<Item = u64>) -> Result<u64> { let mut max = 0; for id in ids { if id > max { @@ -14,7 +14,7 @@ pub fn part1(ids: impl Iterator<Item = i64>) -> Result<i64> { Ok(max) } -pub fn part2(ids: impl Iterator<Item = i64>) -> Result<i64> { +pub fn part2(ids: impl Iterator<Item = u64>) -> Result<u64> { let mut seats = vec![false; 1024]; for id in ids { seats[id as usize] = true; @@ -35,7 +35,7 @@ pub fn part2(ids: impl Iterator<Item = i64>) -> Result<i64> { Ok(seat.try_into()?) } -fn seat_id(desc: &str) -> Result<i64> { +fn seat_id(desc: &str) -> Result<u64> { if desc.len() != 10 { return Err(anyhow!("invalid desc {}", desc)); } diff --git a/src/2020/6/mod.rs b/src/bin/2020/day6.rs index 0f61621..114d05f 100644 --- a/src/2020/6/mod.rs +++ b/src/bin/2020/day6.rs @@ -1,15 +1,15 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<impl Iterator<Item = String>> { - Ok(parse::lines(fh)) + Ok(parse::raw_lines(fh)) } -pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part1(lines: impl Iterator<Item = String>) -> Result<usize> { let mut yes = HashSet::new(); let mut total = 0; for line in lines { if line.is_empty() { - total += yes.len() as i64; + total += yes.len(); yes = HashSet::new(); } else { for c in line.chars() { @@ -17,11 +17,11 @@ pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { } } } - total += yes.len() as i64; + total += yes.len(); Ok(total) } -pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part2(lines: impl Iterator<Item = String>) -> Result<usize> { let mut yes = HashSet::new(); for c in 'a'..='z' { yes.insert(c); @@ -29,7 +29,7 @@ pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { let mut total = 0; for line in lines { if line.is_empty() { - total += yes.len() as i64; + total += yes.len(); yes = HashSet::new(); for c in 'a'..='z' { yes.insert(c); @@ -42,7 +42,7 @@ pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { } } } - total += yes.len() as i64; + total += yes.len(); Ok(total) } diff --git a/src/2020/7/mod.rs b/src/bin/2020/day7.rs index 2c8a1a7..ac6c74a 100644 --- a/src/2020/7/mod.rs +++ b/src/bin/2020/day7.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -type Graph = HashMap<String, Vec<(i64, String)>>; +type Graph = HashMap<String, Vec<(u64, String)>>; pub fn parse(fh: File) -> Result<Graph> { let input = parse::string(fh); @@ -12,7 +12,7 @@ pub fn parse(fh: File) -> Result<Graph> { Ok(graph) } -pub fn part1(graph: Graph) -> Result<i64> { +pub fn part1(graph: Graph) -> Result<u64> { let mut colors = 0; for color in graph.keys() { if bag_contains(&graph, color, "shiny gold")? { @@ -22,12 +22,12 @@ pub fn part1(graph: Graph) -> Result<i64> { Ok(colors) } -pub fn part2(graph: Graph) -> Result<i64> { +pub fn part2(graph: Graph) -> Result<u64> { // subtract 1 to not count the shiny gold bag itself count_bags(&graph, "shiny gold").map(|i| i - 1) } -fn parse_line(line: &str) -> Result<(String, Vec<(i64, String)>)> { +fn parse_line(line: &str) -> Result<(String, Vec<(u64, String)>)> { let captures = regex_captures!(r"^(.*) bags contain (.*)\.$", line) .context("line failed to match regex")?; let color = captures.get(1).unwrap().as_str(); @@ -78,7 +78,7 @@ fn bag_contains(graph: &Graph, start: &str, target: &str) -> Result<bool> { Ok(false) } -fn count_bags(graph: &Graph, color: &str) -> Result<i64> { +fn count_bags(graph: &Graph, color: &str) -> Result<u64> { Ok(1 + graph .get(&color.to_string()) .context("failed to find starting color in graph")? @@ -86,7 +86,7 @@ fn count_bags(graph: &Graph, color: &str) -> Result<i64> { .map(|(count, child)| Ok(count * count_bags(graph, child)?)) .collect::<Result<Vec<_>>>()? .iter() - .sum::<i64>()) + .sum::<u64>()) } #[test] diff --git a/src/2020/8/mod.rs b/src/bin/2020/day8.rs index af08f5c..06861f5 100644 --- a/src/2020/8/mod.rs +++ b/src/bin/2020/day8.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Clone, Copy)] enum OpType { @@ -44,7 +44,7 @@ impl std::str::FromStr for Op { } pub fn parse(fh: File) -> Result<Vec<Op>> { - parse::lines(fh).map(|line| line.parse()).collect() + Ok(parse::lines(fh).collect()) } pub fn part1(opcodes: Vec<Op>) -> Result<i64> { diff --git a/src/2020/9/mod.rs b/src/bin/2020/day9.rs index 0d2dd6f..becae3b 100644 --- a/src/2020/9/mod.rs +++ b/src/bin/2020/day9.rs @@ -1,12 +1,12 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; const WINDOW: usize = 25; -pub fn parse(fh: File) -> Result<Vec<i64>> { - Ok(parse::ints(parse::lines(fh)).collect()) +pub fn parse(fh: File) -> Result<Vec<u64>> { + Ok(parse::lines(fh).collect()) } -pub fn part1(list: Vec<i64>) -> Result<i64> { +pub fn part1(list: Vec<u64>) -> Result<u64> { for i in 0..(list.len() - WINDOW) { let set = &list[i..i + WINDOW]; let n = list[i + WINDOW]; @@ -18,7 +18,7 @@ pub fn part1(list: Vec<i64>) -> Result<i64> { Err(anyhow!("failed to find invalid number")) } -pub fn part2(list: Vec<i64>) -> Result<i64> { +pub fn part2(list: Vec<u64>) -> Result<u64> { let mut invalid = None; for i in 0..(list.len() - WINDOW) { let set = &list[i..i + WINDOW]; @@ -45,7 +45,7 @@ pub fn part2(list: Vec<i64>) -> Result<i64> { Err(anyhow!("failed to find sequence summing to invalid number")) } -fn valid(set: &[i64], n: i64) -> bool { +fn valid(set: &[u64], n: u64) -> bool { for i in 0..set.len() { for j in 0..set.len() { if i == j { diff --git a/src/bin/2020/main.rs b/src/bin/2020/main.rs new file mode 100644 index 0000000..354f6b0 --- /dev/null +++ b/src/bin/2020/main.rs @@ -0,0 +1,42 @@ +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::similar_names)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::type_complexity)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::collapsible_if)] +#![allow(clippy::comparison_chain)] + +use advent_of_code::prelude::*; + +mod day1; +mod day2; +mod day3; +mod day4; +mod day5; +mod day6; +mod day7; +mod day8; +mod day9; +// NEXT MOD + +#[paw::main] +fn main(opt: Opt) -> Result<()> { + #[allow(clippy::match_single_binding)] + match opt.day { + 1 => advent_of_code::day!(2020, opt.day, opt.puzzle, day1), + 2 => advent_of_code::day!(2020, opt.day, opt.puzzle, day2), + 3 => advent_of_code::day!(2020, opt.day, opt.puzzle, day3), + 4 => advent_of_code::day!(2020, opt.day, opt.puzzle, day4), + 5 => advent_of_code::day!(2020, opt.day, opt.puzzle, day5), + 6 => advent_of_code::day!(2020, opt.day, opt.puzzle, day6), + 7 => advent_of_code::day!(2020, opt.day, opt.puzzle, day7), + 8 => advent_of_code::day!(2020, opt.day, opt.puzzle, day8), + 9 => advent_of_code::day!(2020, opt.day, opt.puzzle, day9), + // NEXT PART + _ => panic!("unknown day {}", opt.day), + } + Ok(()) +} diff --git a/src/2021/1/mod.rs b/src/bin/2021/day1.rs index c01714a..fce763c 100644 --- a/src/2021/1/mod.rs +++ b/src/bin/2021/day1.rs @@ -1,19 +1,18 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<Vec<i64>> { - Ok(parse::ints(parse::lines(fh)).collect()) + Ok(parse::lines(fh).collect()) } -pub fn part1(ints: Vec<i64>) -> Result<i64> { +pub fn part1(ints: Vec<i64>) -> Result<usize> { Ok(ints .windows(2) .map(|a| a[1] - a[0]) .filter(|x| *x > 0) - .count() - .try_into()?) + .count()) } -pub fn part2(ints: Vec<i64>) -> Result<i64> { +pub fn part2(ints: Vec<i64>) -> Result<usize> { Ok(ints .windows(3) .map(|a| a[0] + a[1] + a[2]) @@ -21,8 +20,7 @@ pub fn part2(ints: Vec<i64>) -> Result<i64> { .windows(2) .map(|a| a[1] - a[0]) .filter(|x| *x > 0) - .count() - .try_into()?) + .count()) } #[test] diff --git a/src/2021/10/mod.rs b/src/bin/2021/day10.rs index 4a51a9e..d7b5f48 100644 --- a/src/2021/10/mod.rs +++ b/src/bin/2021/day10.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<impl Iterator<Item = String>> { - Ok(parse::lines(fh)) + Ok(parse::raw_lines(fh)) } -pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part1(lines: impl Iterator<Item = String>) -> Result<u64> { let mut total = 0; for line in lines { let mut open = vec![]; @@ -44,7 +44,7 @@ pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { Ok(total) } -pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part2(lines: impl Iterator<Item = String>) -> Result<u64> { let mut scores = vec![]; for line in lines { let mut open = vec![]; diff --git a/src/2021/11/mod.rs b/src/bin/2021/day11.rs index c153ddc..fac392e 100644 --- a/src/2021/11/mod.rs +++ b/src/bin/2021/day11.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -fn iterate(grid: &mut Grid<(u8, bool)>) -> i64 { +fn iterate(grid: &mut Grid<(u8, bool)>) -> usize { let mut flashes = 0; for (cell, _) in grid.cells_mut() { *cell += 1; @@ -43,13 +43,13 @@ fn iterate(grid: &mut Grid<(u8, bool)>) -> i64 { } pub fn parse(fh: File) -> Result<Grid<(u8, bool)>> { - Ok(parse::digit_grid(parse::lines(fh)) + Ok(parse::digit_grid(parse::raw_lines(fh)) .indexed_cells() .map(|((row, col), cell)| ((row, col), (*cell, false))) .collect()) } -pub fn part1(mut map: Grid<(u8, bool)>) -> Result<i64> { +pub fn part1(mut map: Grid<(u8, bool)>) -> Result<usize> { let mut flashes = 0; for _ in 0..100 { flashes += iterate(&mut map); @@ -57,11 +57,11 @@ pub fn part1(mut map: Grid<(u8, bool)>) -> Result<i64> { Ok(flashes) } -pub fn part2(mut map: Grid<(u8, bool)>) -> Result<i64> { +pub fn part2(mut map: Grid<(u8, bool)>) -> Result<usize> { let mut step = 1; loop { let flashes = iterate(&mut map); - if flashes == (map.rows().0 * map.cols().0).try_into()? { + if flashes == (map.rows().0 * map.cols().0) { break; } step += 1; diff --git a/src/2021/12/mod.rs b/src/bin/2021/day12.rs index 7c7d601..2770aa6 100644 --- a/src/2021/12/mod.rs +++ b/src/bin/2021/day12.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; fn small(s: &str) -> bool { s.bytes().all(|c| c.is_ascii_lowercase()) @@ -21,7 +21,7 @@ fn single_small<'a>(path: impl Iterator<Item = &'a str>) -> bool { fn paths_from1<'a>( graph: &'a HashMap<String, HashSet<String>>, path: &mut Vec<&'a str>, -) -> i64 { +) -> u64 { let mut total = 0; for neighbor in graph[path[path.len() - 1]].iter() { if small(neighbor) && path.contains(&neighbor.as_ref()) { @@ -41,7 +41,7 @@ fn paths_from1<'a>( fn paths_from2<'a>( graph: &'a HashMap<String, HashSet<String>>, path: &mut Vec<&'a str>, -) -> i64 { +) -> u64 { let mut total = 0; for neighbor in graph[path[path.len() - 1]].iter() { if neighbor == "start" { @@ -66,9 +66,8 @@ fn paths_from2<'a>( pub fn parse(fh: File) -> Result<HashMap<String, HashSet<String>>> { let mut graph = HashMap::new(); - for line in parse::lines(fh) { - let nodes: Vec<String> = - line.split('-').map(|s| s.to_string()).collect(); + for line in parse::raw_lines(fh) { + let nodes: Vec<_> = line.split('-').map(|s| s.to_string()).collect(); let edges = graph.entry(nodes[0].clone()).or_insert_with(HashSet::new); edges.insert(nodes[1].clone()); @@ -79,11 +78,11 @@ pub fn parse(fh: File) -> Result<HashMap<String, HashSet<String>>> { Ok(graph) } -pub fn part1(graph: HashMap<String, HashSet<String>>) -> Result<i64> { +pub fn part1(graph: HashMap<String, HashSet<String>>) -> Result<u64> { Ok(paths_from1(&graph, &mut vec!["start"])) } -pub fn part2(graph: HashMap<String, HashSet<String>>) -> Result<i64> { +pub fn part2(graph: HashMap<String, HashSet<String>>) -> Result<u64> { Ok(paths_from2(&graph, &mut vec!["start"])) } diff --git a/src/2021/13/mod.rs b/src/bin/2021/day13.rs index 6dd9b95..75e547b 100644 --- a/src/2021/13/mod.rs +++ b/src/bin/2021/day13.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Default)] pub struct Paper { @@ -73,8 +73,8 @@ impl Paper { *self = clone; } - fn total(&self) -> i64 { - self.grid.cells().map(|b| i64::from(*b)).sum() + fn total(&self) -> usize { + self.grid.cells().filter(|b| **b).count() } } @@ -94,7 +94,7 @@ impl std::fmt::Display for Paper { pub fn parse(fh: File) -> Result<(Paper, Vec<(bool, usize)>)> { let mut paper = Paper::default(); let mut folds = vec![]; - for line in parse::lines(fh) { + for line in parse::raw_lines(fh) { if line.is_empty() { continue; } @@ -113,12 +113,16 @@ pub fn parse(fh: File) -> Result<(Paper, Vec<(bool, usize)>)> { Ok((paper, folds)) } -pub fn part1((mut paper, folds): (Paper, Vec<(bool, usize)>)) -> Result<i64> { +pub fn part1( + (mut paper, folds): (Paper, Vec<(bool, usize)>), +) -> Result<usize> { paper.fold(folds[0].0, folds[0].1); Ok(paper.total()) } -pub fn part2((mut paper, folds): (Paper, Vec<(bool, usize)>)) -> Result<i64> { +pub fn part2( + (mut paper, folds): (Paper, Vec<(bool, usize)>), +) -> Result<usize> { for fold in folds { paper.fold(fold.0, fold.1); } diff --git a/src/2021/14/mod.rs b/src/bin/2021/day14.rs index b7e3714..0080015 100644 --- a/src/2021/14/mod.rs +++ b/src/bin/2021/day14.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; fn process(polymer: &[u8], rules: &HashMap<Vec<u8>, u8>) -> Vec<u8> { let mut insertions = vec![]; @@ -17,7 +17,7 @@ fn process(polymer: &[u8], rules: &HashMap<Vec<u8>, u8>) -> Vec<u8> { } pub fn parse(fh: File) -> Result<(Vec<u8>, HashMap<Vec<u8>, u8>)> { - let mut lines = parse::lines(fh); + let mut lines = parse::raw_lines(fh); let polymer = lines.next().unwrap(); lines.next(); @@ -31,7 +31,7 @@ pub fn parse(fh: File) -> Result<(Vec<u8>, HashMap<Vec<u8>, u8>)> { pub fn part1( (mut polymer, rules): (Vec<u8>, HashMap<Vec<u8>, u8>), -) -> Result<i64> { +) -> Result<u64> { for _ in 0..10 { polymer = process(&polymer, &rules); } @@ -45,7 +45,7 @@ pub fn part1( pub fn part2( (polymer, rules): (Vec<u8>, HashMap<Vec<u8>, u8>), -) -> Result<i64> { +) -> Result<u64> { let mut pairs = HashMap::new(); for pair in polymer.windows(2) { let count = pairs.entry([pair[0], pair[1]]).or_insert(0); diff --git a/src/2021/15/mod.rs b/src/bin/2021/day15.rs index 15b05fb..ca7a72f 100644 --- a/src/2021/15/mod.rs +++ b/src/bin/2021/day15.rs @@ -1,28 +1,28 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Map { grid: Grid<u8>, } -impl crate::graph::Graph<(Row, Col), (Row, Col)> for Map { - type Edges = crate::grid::Adjacent; +impl advent_of_code::graph::Graph<(Row, Col), (Row, Col)> for Map { + type Edges = advent_of_code::grid::Adjacent; fn edges(&self, v: (Row, Col)) -> Self::Edges { self.grid.adjacent(v.0, v.1, false) } - fn edge(&self, _v: (Row, Col), e: (Row, Col)) -> ((Row, Col), i64) { - (e, i64::from(self.grid[e.0][e.1])) + fn edge(&self, _v: (Row, Col), e: (Row, Col)) -> ((Row, Col), u64) { + (e, u64::from(self.grid[e.0][e.1])) } } pub fn parse(fh: File) -> Result<Map> { Ok(Map { - grid: parse::digit_grid(parse::lines(fh)), + grid: parse::digit_grid(parse::raw_lines(fh)), }) } -pub fn part1(map: Map) -> Result<i64> { +pub fn part1(map: Map) -> Result<u64> { Ok(map .dijkstra( (Row(0), Col(0)), @@ -31,7 +31,7 @@ pub fn part1(map: Map) -> Result<i64> { .0) } -pub fn part2(map: Map) -> Result<i64> { +pub fn part2(map: Map) -> Result<u64> { let mut large_grid = Grid::default(); large_grid.grow(Row(map.grid.rows().0 * 5), Col(map.grid.cols().0 * 5)); for lrow in 0..5 { diff --git a/src/2021/16/mod.rs b/src/bin/2021/day16.rs index 797f50a..3177483 100644 --- a/src/2021/16/mod.rs +++ b/src/bin/2021/day16.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; struct BitIter { byte: u8, @@ -120,9 +120,9 @@ impl Packet { Subpackets { to_return } } - fn eval(&self) -> i64 { + fn eval(&self) -> u64 { match &self.contents { - PacketContents::Literal { value } => (*value).try_into().unwrap(), + PacketContents::Literal { value } => *value, PacketContents::Operator { packets } => match self.id { 0 => packets.iter().map(|packet| packet.eval()).sum(), 1 => packets.iter().map(|packet| packet.eval()).product(), @@ -133,9 +133,9 @@ impl Packet { packets.iter().map(|packet| packet.eval()).max().unwrap() } 4 => unreachable!(), - 5 => i64::from(packets[0].eval() > packets[1].eval()), - 6 => i64::from(packets[0].eval() < packets[1].eval()), - 7 => i64::from(packets[0].eval() == packets[1].eval()), + 5 => u64::from(packets[0].eval() > packets[1].eval()), + 6 => u64::from(packets[0].eval() < packets[1].eval()), + 7 => u64::from(packets[0].eval() == packets[1].eval()), _ => unreachable!(), }, } @@ -178,7 +178,7 @@ impl<'a> Iterator for Subpackets<'a> { } pub fn parse(fh: File) -> Result<Packet> { - let line = parse::lines(fh).next().unwrap(); + let line = parse::raw_lines(fh).next().unwrap(); let mut bits = bits(line.as_bytes().chunks(2).map(|bs| { u8::from_str_radix(std::str::from_utf8(bs).unwrap(), 16).unwrap() })); @@ -186,14 +186,14 @@ pub fn parse(fh: File) -> Result<Packet> { Ok(packet) } -pub fn part1(packet: Packet) -> Result<i64> { +pub fn part1(packet: Packet) -> Result<u64> { Ok(packet .subpackets() - .map(|packet| i64::from(packet.version)) + .map(|packet| u64::from(packet.version)) .sum()) } -pub fn part2(packet: Packet) -> Result<i64> { +pub fn part2(packet: Packet) -> Result<u64> { Ok(packet.eval()) } diff --git a/src/2021/17/mod.rs b/src/bin/2021/day17.rs index b3bf5ad..54ee4bb 100644 --- a/src/2021/17/mod.rs +++ b/src/bin/2021/day17.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; fn fire( mut xv: i64, @@ -40,7 +40,7 @@ fn fire( pub fn parse( fh: File, ) -> Result<(std::ops::RangeInclusive<i64>, std::ops::RangeInclusive<i64>)> { - let line = parse::lines(fh).next().unwrap(); + let line = parse::raw_lines(fh).next().unwrap(); let captures = regex_captures!( r"target area: x=(-?\d+)..(-?\d+), y=(-?\d+)..(-?\d+)", &line, @@ -79,7 +79,7 @@ pub fn part2( std::ops::RangeInclusive<i64>, std::ops::RangeInclusive<i64>, ), -) -> Result<i64> { +) -> Result<u64> { let mut count = 0; for xv in *xrange.start().min(&0)..=*xrange.end().max(&0) { for yv in *yrange.start().min(&0) diff --git a/src/2021/18/mod.rs b/src/bin/2021/day18.rs index 56801ff..6a7e73d 100644 --- a/src/2021/18/mod.rs +++ b/src/bin/2021/day18.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Clone)] pub enum Number { @@ -6,6 +6,14 @@ pub enum Number { Pair(Box<Number>, Box<Number>), } +impl std::str::FromStr for Number { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(Self::parse(s)) + } +} + impl Number { fn parse(s: &str) -> Self { if s.starts_with('[') { @@ -144,9 +152,9 @@ impl Number { } } - fn magnitude(&self) -> i64 { + fn magnitude(&self) -> u64 { match self { - Self::Value(n) => i64::from(*n), + Self::Value(n) => u64::from(*n), Self::Pair(left, right) => { left.magnitude() * 3 + right.magnitude() * 2 } @@ -211,15 +219,15 @@ impl std::fmt::Display for Number { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Number>> { - Ok(parse::lines(fh).map(|line| Number::parse(&line))) + Ok(parse::lines(fh)) } -pub fn part1(numbers: impl Iterator<Item = Number>) -> Result<i64> { +pub fn part1(numbers: impl Iterator<Item = Number>) -> Result<u64> { let sum: Number = numbers.sum(); Ok(sum.magnitude()) } -pub fn part2(numbers: impl Iterator<Item = Number>) -> Result<i64> { +pub fn part2(numbers: impl Iterator<Item = Number>) -> Result<u64> { let nums: Vec<_> = numbers.collect(); let mut max = 0; for (i, n1) in nums.iter().enumerate() { diff --git a/src/2021/19/mod.rs b/src/bin/2021/day19.rs index 6a9b66a..735cb19 100644 --- a/src/2021/19/mod.rs +++ b/src/bin/2021/day19.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; const ORIENTATIONS: &[&dyn Fn(Point) -> Point] = &[ &|p| Point::new(p.y, p.z, p.x), @@ -171,10 +171,10 @@ impl Scan { } pub fn parse(fh: File) -> Result<Scan> { - Ok(Scan::parse(parse::lines(fh))) + Ok(Scan::parse(parse::raw_lines(fh))) } -pub fn part1(scan: Scan) -> Result<i64> { +pub fn part1(scan: Scan) -> Result<usize> { let mut beacons: HashSet<Point> = HashSet::new(); let mut skip = None; for (i, scanner1) in scan.scanners().iter().enumerate() { @@ -217,10 +217,10 @@ pub fn part1(scan: Scan) -> Result<i64> { break; } } - Ok(beacons.len().try_into()?) + Ok(beacons.len()) } -pub fn part2(scan: Scan) -> Result<i64> { +pub fn part2(scan: Scan) -> Result<i16> { let mut beacons: HashSet<Point> = HashSet::new(); let mut skip = None; let mut offsets = vec![]; @@ -277,7 +277,7 @@ pub fn part2(scan: Scan) -> Result<i64> { } } } - Ok(max.into()) + Ok(max) } #[test] diff --git a/src/2021/2/mod.rs b/src/bin/2021/day2.rs index afbc3f0..5ae3596 100644 --- a/src/2021/2/mod.rs +++ b/src/bin/2021/day2.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub enum Command { Forward(i64), @@ -7,7 +7,7 @@ pub enum Command { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Command>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { if let Some(n) = line.strip_prefix("forward ") { Command::Forward(n.parse().unwrap()) } else if let Some(n) = line.strip_prefix("down ") { diff --git a/src/2021/20/mod.rs b/src/bin/2021/day20.rs index 292a2b2..4ff8b7d 100644 --- a/src/2021/20/mod.rs +++ b/src/bin/2021/day20.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Image { algorithm: Vec<bool>, @@ -56,16 +56,16 @@ impl Image { } } - fn count_true(&self) -> i64 { + fn count_true(&self) -> usize { if self.outer { panic!("infinite"); } - self.map.cells().filter(|c| **c).count().try_into().unwrap() + self.map.cells().filter(|c| **c).count() } } pub fn parse(fh: File) -> Result<Image> { - let mut lines = parse::lines(fh); + let mut lines = parse::raw_lines(fh); let algorithm = lines.next().unwrap(); let algorithm: Vec<_> = algorithm .as_bytes() @@ -81,14 +81,14 @@ pub fn parse(fh: File) -> Result<Image> { Ok(Image::new(algorithm, map)) } -pub fn part1(mut image: Image) -> Result<i64> { +pub fn part1(mut image: Image) -> Result<usize> { for _ in 0..2 { image.enhance(); } Ok(image.count_true()) } -pub fn part2(mut image: Image) -> Result<i64> { +pub fn part2(mut image: Image) -> Result<usize> { for _ in 0..50 { image.enhance(); } diff --git a/src/2021/21/mod.rs b/src/bin/2021/day21.rs index 21fbedd..2cf6bfe 100644 --- a/src/2021/21/mod.rs +++ b/src/bin/2021/day21.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Clone)] pub struct Game { @@ -167,7 +167,7 @@ impl Game { } pub fn parse(fh: File) -> Result<Game> { - let mut lines = parse::lines(fh); + let mut lines = parse::raw_lines(fh); let p1 = lines .next() .unwrap() diff --git a/src/2021/22/mod.rs b/src/bin/2021/day22.rs index b554baa..ed8a0de 100644 --- a/src/2021/22/mod.rs +++ b/src/bin/2021/day22.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] struct Point3D { @@ -169,10 +169,10 @@ impl Reactor { } pub fn parse(fh: File) -> Result<Reactor> { - Ok(Reactor::parse(parse::lines(fh))) + Ok(Reactor::parse(parse::raw_lines(fh))) } -pub fn part1(reactor: Reactor) -> Result<i64> { +pub fn part1(reactor: Reactor) -> Result<u64> { let mut total = 0; for x in -50..=50 { for y in -50..=50 { diff --git a/src/2021/23/mod.rs b/src/bin/2021/day23.rs index 632dbaf..c86f7c0 100644 --- a/src/2021/23/mod.rs +++ b/src/bin/2021/day23.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; static CONNECTIVITY1: &[&[&[usize]]] = &[ &[ @@ -1198,7 +1198,7 @@ enum Amphipod { use Amphipod::*; impl Amphipod { - fn step_cost(&self) -> i64 { + fn step_cost(&self) -> u64 { match self { A => 1, B => 10, @@ -1304,9 +1304,9 @@ impl Burrow { done } - fn move_cost(&self, mv: Move) -> i64 { + fn move_cost(&self, mv: Move) -> u64 { self.spaces[mv.from].unwrap().step_cost() - * i64::try_from(self.path(mv.from, mv.to).len()).unwrap() + * u64::try_from(self.path(mv.from, mv.to).len()).unwrap() } fn make_move(&self, mv: Move) -> Self { @@ -1673,21 +1673,21 @@ impl Move { struct Pathfinder; -impl crate::graph::Graph<Burrow, Move> for Pathfinder { +impl advent_of_code::graph::Graph<Burrow, Move> for Pathfinder { type Edges = Vec<Move>; fn edges(&self, v: Burrow) -> Self::Edges { v.legal_moves() } - fn edge(&self, v: Burrow, e: Move) -> (Burrow, i64) { + fn edge(&self, v: Burrow, e: Move) -> (Burrow, u64) { (v.make_move(e), v.move_cost(e)) } } pub fn parse(fh: File) -> Result<Burrow> { let mut burrow = Burrow::default(); - let lines: Vec<_> = parse::lines(fh).collect(); + let lines: Vec<_> = parse::raw_lines(fh).collect(); let captures = regex_captures!(r"###(.)#(.)#(.)#(.)###", &lines[2]).unwrap(); @@ -1706,7 +1706,7 @@ pub fn parse(fh: File) -> Result<Burrow> { Ok(burrow) } -pub fn part1(burrow: Burrow) -> Result<i64> { +pub fn part1(burrow: Burrow) -> Result<u64> { let (cost, _path) = Pathfinder.dijkstra(burrow, Burrow::done(false)); // for burrow in path { // eprintln!("{}", burrow); @@ -1714,7 +1714,7 @@ pub fn part1(burrow: Burrow) -> Result<i64> { Ok(cost) } -pub fn part2(burrow: Burrow) -> Result<i64> { +pub fn part2(burrow: Burrow) -> Result<u64> { let (cost, _path) = Pathfinder.dijkstra(burrow.to_big(), Burrow::done(true)); // for burrow in path { diff --git a/src/2021/24/mod.rs b/src/bin/2021/day24.rs index 4114382..54788ec 100644 --- a/src/2021/24/mod.rs +++ b/src/bin/2021/day24.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Debug, Clone, Copy)] pub enum Op { @@ -243,7 +243,7 @@ fn run(inp: &[i64], ops: &[Op]) -> Option<i64> { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Op>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { let captures = regex_captures!( r"(inp|add|mul|div|mod|eql) ([wxyz])(?: ([wxyz]|-?\d+))?", &line diff --git a/src/2021/25/mod.rs b/src/bin/2021/day25.rs index 22a31cd..ed396c6 100644 --- a/src/2021/25/mod.rs +++ b/src/bin/2021/day25.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Debug, Clone, Eq, PartialEq)] pub enum Cell { @@ -60,7 +60,7 @@ impl Map { pub fn parse(fh: File) -> Result<Map> { Ok(Map { - grid: parse::grid(parse::lines(fh), |b| match b { + grid: parse::grid(parse::raw_lines(fh), |b| match b { b'v' => Cell::Down, b'>' => Cell::Right, b'.' => Cell::None, @@ -69,7 +69,7 @@ pub fn parse(fh: File) -> Result<Map> { }) } -pub fn part1(map: Map) -> Result<i64> { +pub fn part1(map: Map) -> Result<u64> { let mut prev = map; let mut i = 0; loop { diff --git a/src/2021/3/mod.rs b/src/bin/2021/day3.rs index a512cac..70a3085 100644 --- a/src/2021/3/mod.rs +++ b/src/bin/2021/day3.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<impl Iterator<Item = String>> { - Ok(parse::lines(fh)) + Ok(parse::raw_lines(fh)) } -pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part1(lines: impl Iterator<Item = String>) -> Result<u64> { let (total_lines, by_pos) = pos_counts(lines)?; let gamma: String = by_pos .iter() @@ -17,7 +17,7 @@ pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { Ok(bin_str_to_int(&gamma) * bin_str_to_int(&epsilon)) } -pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part2(lines: impl Iterator<Item = String>) -> Result<u64> { let mut oxygen: Vec<_> = lines.collect(); let mut co2 = oxygen.clone(); @@ -79,11 +79,11 @@ fn pos_counts( Ok((total_lines, by_pos)) } -fn bin_str_to_int(s: &str) -> i64 { +fn bin_str_to_int(s: &str) -> u64 { let mut ret = 0; for (i, c) in s.chars().rev().enumerate() { if c == '1' { - ret += 2i64.pow(i.try_into().unwrap()); + ret += 2u64.pow(i.try_into().unwrap()); } } ret diff --git a/src/2021/4/mod.rs b/src/bin/2021/day4.rs index c1b0cd2..f733078 100644 --- a/src/2021/4/mod.rs +++ b/src/bin/2021/day4.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Debug)] struct Board { @@ -39,12 +39,18 @@ impl Board { } } - fn value(&self) -> i64 { + fn value(&self) -> u64 { self.marked .iter() .zip(self.numbers.iter()) .filter_map( - |(marked, n)| if !*marked { Some(*n as i64) } else { None }, + |(marked, n)| { + if !*marked { + Some(u64::from(*n)) + } else { + None + } + }, ) .sum() } @@ -58,7 +64,7 @@ pub struct Game { impl Game { fn parse<T: std::io::Read>(input: T) -> Result<Self> { - let mut lines = parse::lines(input).peekable(); + let mut lines = parse::raw_lines(input).peekable(); let line = lines.next().ok_or_else(|| anyhow!("missing line"))?; let inputs = line @@ -132,17 +138,17 @@ pub fn parse(fh: File) -> Result<Game> { Game::parse(fh) } -pub fn part1(game: Game) -> Result<i64> { +pub fn part1(game: Game) -> Result<u64> { if let Some((n, board)) = game.find_first_winner() { - Ok((n as i64) * board.value()) + Ok(u64::from(n) * board.value()) } else { bail!("couldn't find winner") } } -pub fn part2(game: Game) -> Result<i64> { +pub fn part2(game: Game) -> Result<u64> { if let Some((n, board)) = game.find_last_winner() { - Ok((n as i64) * board.value()) + Ok(u64::from(n) * board.value()) } else { bail!("couldn't find winner") } diff --git a/src/2021/5/mod.rs b/src/bin/2021/day5.rs index 4b472b2..68bca56 100644 --- a/src/2021/5/mod.rs +++ b/src/bin/2021/day5.rs @@ -1,4 +1,4 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Default, Clone)] struct Map { @@ -73,7 +73,7 @@ impl Map { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Vec<usize>>> { - Ok(parse::lines(fh).map(move |line| { + Ok(parse::raw_lines(fh).map(move |line| { regex_captures!(r"^(\d+),(\d+) -> (\d+),(\d+)$", &line) .unwrap() .iter() @@ -84,16 +84,16 @@ pub fn parse(fh: File) -> Result<impl Iterator<Item = Vec<usize>>> { })) } -pub fn part1(coords: impl Iterator<Item = Vec<usize>>) -> Result<i64> { +pub fn part1(coords: impl Iterator<Item = Vec<usize>>) -> Result<usize> { let mut map = Map::default(); for nums in coords { let _ = map.mark_horizontal(nums[0], nums[1], nums[2], nums[3]) || map.mark_vertical(nums[0], nums[1], nums[2], nums[3]); } - Ok(map.count_overlapping().try_into()?) + Ok(map.count_overlapping()) } -pub fn part2(coords: impl Iterator<Item = Vec<usize>>) -> Result<i64> { +pub fn part2(coords: impl Iterator<Item = Vec<usize>>) -> Result<usize> { let mut map = Map::default(); for nums in coords { if map.mark_horizontal(nums[0], nums[1], nums[2], nums[3]) { @@ -107,7 +107,7 @@ pub fn part2(coords: impl Iterator<Item = Vec<usize>>) -> Result<i64> { } unreachable!(); } - Ok(map.count_overlapping().try_into()?) + Ok(map.count_overlapping()) } #[test] diff --git a/src/2021/6/mod.rs b/src/bin/2021/day6.rs index e2dafff..039209e 100644 --- a/src/2021/6/mod.rs +++ b/src/bin/2021/day6.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -pub fn parse(fh: File) -> Result<Vec<i64>> { - Ok(parse::ints(parse::split(fh, b',')).collect()) +pub fn parse(fh: File) -> Result<Vec<usize>> { + Ok(parse::split(fh, b',').collect()) } -pub fn part1(mut fishes: Vec<i64>) -> Result<i64> { +pub fn part1(mut fishes: Vec<usize>) -> Result<usize> { for _ in 0..80 { let mut new = 0; for fish in fishes.iter_mut() { @@ -17,14 +17,14 @@ pub fn part1(mut fishes: Vec<i64>) -> Result<i64> { } fishes.resize(fishes.len() + new, 8); } - Ok(fishes.len().try_into()?) + Ok(fishes.len()) } -pub fn part2(fishes: Vec<i64>) -> Result<i64> { +pub fn part2(fishes: Vec<usize>) -> Result<usize> { let mut by_age = VecDeque::new(); by_age.resize(9, 0); for fish in fishes { - by_age[fish as usize] += 1; + by_age[fish] += 1; } for _ in 0..256 { let new = by_age.pop_front().unwrap(); diff --git a/src/2021/7/mod.rs b/src/bin/2021/day7.rs index 8ddd46e..56eaeb1 100644 --- a/src/2021/7/mod.rs +++ b/src/bin/2021/day7.rs @@ -1,26 +1,26 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; -pub fn parse(fh: File) -> Result<Vec<i64>> { - Ok(parse::ints(parse::split(fh, b',')).collect()) +pub fn parse(fh: File) -> Result<Vec<usize>> { + Ok(parse::split(fh, b',').collect()) } -pub fn part1(crabs: Vec<i64>) -> Result<i64> { +pub fn part1(crabs: Vec<usize>) -> Result<usize> { Ok((0..=crabs.iter().copied().max().unwrap()) .map(|start| { - crabs.iter().copied().map(|crab| (crab - start).abs()).sum() + crabs.iter().copied().map(|crab| crab.abs_diff(start)).sum() }) .min() .unwrap()) } -pub fn part2(crabs: Vec<i64>) -> Result<i64> { +pub fn part2(crabs: Vec<usize>) -> Result<usize> { Ok((0..=crabs.iter().copied().max().unwrap()) .map(|start| { crabs .iter() .copied() .map(|crab| { - let diff = (crab - start).abs(); + let diff = crab.abs_diff(start); diff * (diff + 1) / 2 }) .sum() diff --git a/src/2021/8/mod.rs b/src/bin/2021/day8.rs index 70d71a0..ca101ef 100644 --- a/src/2021/8/mod.rs +++ b/src/bin/2021/day8.rs @@ -1,9 +1,9 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse( fh: File, ) -> Result<impl Iterator<Item = (Vec<String>, Vec<String>)>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { let parts: Vec<_> = line.split(" | ").collect(); ( parts[0].split(' ').map(str::to_string).collect(), @@ -14,15 +14,13 @@ pub fn parse( pub fn part1( lines: impl Iterator<Item = (Vec<String>, Vec<String>)>, -) -> Result<i64> { - let mut count = 0i64; +) -> Result<usize> { + let mut count = 0; for (_, output) in lines { - let line_count: i64 = output + let line_count = output .iter() .filter(|s| [2, 3, 4, 7].contains(&s.len())) - .count() - .try_into() - .unwrap(); + .count(); count += line_count; } Ok(count) @@ -37,7 +35,7 @@ pub fn part1( // 66 pub fn part2( lines: impl Iterator<Item = (Vec<String>, Vec<String>)>, -) -> Result<i64> { +) -> Result<usize> { let mut total = 0; for (numbers, output) in lines { let mut segments = ['x'; 7]; @@ -171,7 +169,7 @@ pub fn part2( value[0] * 1000 + value[1] * 100 + value[2] * 10 + value[3]; total += value; } - Ok(total.try_into()?) + Ok(total) } #[test] diff --git a/src/2021/9/mod.rs b/src/bin/2021/day9.rs index a1c343b..c0c1b47 100644 --- a/src/2021/9/mod.rs +++ b/src/bin/2021/day9.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<Grid<u8>> { - Ok(parse::digit_grid(parse::lines(fh))) + Ok(parse::digit_grid(parse::raw_lines(fh))) } -pub fn part1(map: Grid<u8>) -> Result<i64> { +pub fn part1(map: Grid<u8>) -> Result<u64> { let mut risk = 0; for ((row, col), pos) in map.indexed_cells() { if map @@ -12,13 +12,13 @@ pub fn part1(map: Grid<u8>) -> Result<i64> { .map(|(row, col)| map[row][col]) .all(|n| *pos < n) { - risk += 1 + *pos as i64; + risk += 1 + u64::from(*pos); } } Ok(risk) } -pub fn part2(map: Grid<u8>) -> Result<i64> { +pub fn part2(map: Grid<u8>) -> Result<u64> { let mut low = vec![]; for ((row, col), pos) in map.indexed_cells() { if map diff --git a/src/bin/2021/main.rs b/src/bin/2021/main.rs new file mode 100644 index 0000000..1d571dc --- /dev/null +++ b/src/bin/2021/main.rs @@ -0,0 +1,74 @@ +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::similar_names)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::type_complexity)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::collapsible_if)] +#![allow(clippy::comparison_chain)] + +use advent_of_code::prelude::*; + +mod day1; +mod day10; +mod day11; +mod day12; +mod day13; +mod day14; +mod day15; +mod day16; +mod day17; +mod day18; +mod day19; +mod day2; +mod day20; +mod day21; +mod day22; +mod day23; +mod day24; +mod day25; +mod day3; +mod day4; +mod day5; +mod day6; +mod day7; +mod day8; +mod day9; +// NEXT MOD + +#[paw::main] +fn main(opt: Opt) -> Result<()> { + #[allow(clippy::match_single_binding)] + match opt.day { + 1 => advent_of_code::day!(2021, opt.day, opt.puzzle, day1), + 2 => advent_of_code::day!(2021, opt.day, opt.puzzle, day2), + 3 => advent_of_code::day!(2021, opt.day, opt.puzzle, day3), + 4 => advent_of_code::day!(2021, opt.day, opt.puzzle, day4), + 5 => advent_of_code::day!(2021, opt.day, opt.puzzle, day5), + 6 => advent_of_code::day!(2021, opt.day, opt.puzzle, day6), + 7 => advent_of_code::day!(2021, opt.day, opt.puzzle, day7), + 8 => advent_of_code::day!(2021, opt.day, opt.puzzle, day8), + 9 => advent_of_code::day!(2021, opt.day, opt.puzzle, day9), + 10 => advent_of_code::day!(2021, opt.day, opt.puzzle, day10), + 11 => advent_of_code::day!(2021, opt.day, opt.puzzle, day11), + 12 => advent_of_code::day!(2021, opt.day, opt.puzzle, day12), + 13 => advent_of_code::day!(2021, opt.day, opt.puzzle, day13), + 14 => advent_of_code::day!(2021, opt.day, opt.puzzle, day14), + 15 => advent_of_code::day!(2021, opt.day, opt.puzzle, day15), + 16 => advent_of_code::day!(2021, opt.day, opt.puzzle, day16), + 17 => advent_of_code::day!(2021, opt.day, opt.puzzle, day17), + 18 => advent_of_code::day!(2021, opt.day, opt.puzzle, day18), + 19 => advent_of_code::day!(2021, opt.day, opt.puzzle, day19), + 20 => advent_of_code::day!(2021, opt.day, opt.puzzle, day20), + 21 => advent_of_code::day!(2021, opt.day, opt.puzzle, day21), + 22 => advent_of_code::day!(2021, opt.day, opt.puzzle, day22), + 23 => advent_of_code::day!(2021, opt.day, opt.puzzle, day23), + 24 => advent_of_code::day!(2021, opt.day, opt.puzzle, day24), + 25 => advent_of_code::day!(2021, opt.day, opt.puzzle, day25), + // NEXT PART + _ => panic!("unknown day {}", opt.day), + } + Ok(()) +} diff --git a/src/2022/1/mod.rs b/src/bin/2022/day1.rs index d3088b6..1b48b29 100644 --- a/src/2022/1/mod.rs +++ b/src/bin/2022/day1.rs @@ -1,26 +1,26 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; -pub fn parse(fh: File) -> Result<Vec<i64>> { +pub fn parse(fh: File) -> Result<Vec<u64>> { let mut elves = vec![]; - let mut lines = parse::lines(fh).peekable(); + let mut lines = parse::raw_lines(fh).peekable(); while lines.peek().is_some() { let mut calories = 0; for line in parse::chunk(&mut lines) { - calories += line.parse::<i64>()?; + calories += line.parse::<u64>()?; } elves.push(calories); } Ok(elves) } -pub fn part1(elves: Vec<i64>) -> Result<i64> { +pub fn part1(elves: Vec<u64>) -> Result<u64> { Ok(elves.iter().copied().max().unwrap_or(0)) } -pub fn part2(mut elves: Vec<i64>) -> Result<i64> { +pub fn part2(mut elves: Vec<u64>) -> Result<u64> { elves.sort(); Ok(elves.iter().rev().copied().take(3).sum()) } diff --git a/src/2022/10/mod.rs b/src/bin/2022/day10.rs index f582cf4..8f7b617 100644 --- a/src/2022/10/mod.rs +++ b/src/bin/2022/day10.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Cpu { x: i64, @@ -37,7 +37,7 @@ pub enum Op { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Op>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { if line == "noop" { Op::Noop } else if let Some(v) = line.strip_prefix("addx ") { diff --git a/src/2022/11/mod.rs b/src/bin/2022/day11.rs index 8bebb72..faef195 100644 --- a/src/2022/11/mod.rs +++ b/src/bin/2022/day11.rs @@ -1,18 +1,18 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Monkey { - items: VecDeque<i64>, - op: Box<dyn Fn(i64) -> i64>, - divisor: i64, - modulo: i64, - test: i64, + items: VecDeque<u64>, + op: Box<dyn Fn(u64) -> u64>, + divisor: u64, + modulo: u64, + test: u64, if_true: usize, if_false: usize, - count: i64, + count: u64, } impl std::fmt::Debug for Monkey { @@ -32,26 +32,22 @@ impl Monkey { let line = it.next().unwrap(); let cap = regex_captures!( - r"^ Operation: new = old ([+*/-]) (\d+|old)$", + r"^ Operation: new = old ([+*]) (\d+|old)$", &line ) .unwrap(); let op = if &cap[2] == "old" { match &cap[1] { - "+" => Box::new(move |x| x + x) as Box<dyn Fn(i64) -> i64>, - "-" => Box::new(move |_| 0.into()), + "+" => Box::new(move |x| x + x) as Box<dyn Fn(u64) -> u64>, "*" => Box::new(move |x| x * x), - "/" => Box::new(move |_| 1.into()), - _ => panic!("unknown op {}", &cap[1]), + _ => unreachable!(), } } else { - let n: i64 = cap[2].parse().unwrap(); + let n: u64 = cap[2].parse().unwrap(); match &cap[1] { - "+" => Box::new(move |x| x + n) as Box<dyn Fn(i64) -> i64>, - "-" => Box::new(move |x| x - n), + "+" => Box::new(move |x| x + n) as Box<dyn Fn(u64) -> u64>, "*" => Box::new(move |x| x * n), - "/" => Box::new(move |x| x / n), - _ => panic!("unknown op {}", &cap[1]), + _ => unreachable!(), } }; @@ -86,25 +82,25 @@ impl Monkey { } } - fn inspect(&mut self) -> Option<(i64, usize)> { + fn inspect(&mut self) -> Option<(u64, usize)> { let Some(item) = self.items.pop_front() else { return None }; self.count += 1; let item = (self.op)(item); let item = item / self.divisor; let item = item % self.modulo; - if item % self.test == 0.into() { + if item % self.test == 0 { Some((item, self.if_true)) } else { Some((item, self.if_false)) } } - fn catch(&mut self, item: i64) { + fn catch(&mut self, item: u64) { self.items.push_back(item); } - fn set_reduce(&mut self, divisor: i64, modulo: i64) { + fn set_reduce(&mut self, divisor: u64, modulo: u64) { self.divisor = divisor; self.modulo = modulo; } @@ -137,14 +133,14 @@ impl Monkeys { } } - fn monkey_business(&self) -> i64 { + fn monkey_business(&self) -> u64 { let mut counts: Vec<_> = self.monkeys.iter().map(|m| m.count).collect(); counts.sort_unstable(); counts[counts.len() - 1] * counts[counts.len() - 2] } - fn set_reduce(&mut self, divisor: i64) { + fn set_reduce(&mut self, divisor: u64) { let modulo = self.monkeys.iter().map(|m| m.test).product(); for monkey in &mut self.monkeys { monkey.set_reduce(divisor, modulo); @@ -153,10 +149,10 @@ impl Monkeys { } pub fn parse(fh: File) -> Result<Monkeys> { - Ok(Monkeys::parse(parse::lines(fh))) + Ok(Monkeys::parse(parse::raw_lines(fh))) } -pub fn part1(mut monkeys: Monkeys) -> Result<i64> { +pub fn part1(mut monkeys: Monkeys) -> Result<u64> { monkeys.set_reduce(3); for i in 0..20 { monkeys.round(); @@ -164,7 +160,7 @@ pub fn part1(mut monkeys: Monkeys) -> Result<i64> { Ok(monkeys.monkey_business()) } -pub fn part2(mut monkeys: Monkeys) -> Result<i64> { +pub fn part2(mut monkeys: Monkeys) -> Result<u64> { monkeys.set_reduce(1); for i in 0..10_000 { monkeys.round(); @@ -176,10 +172,10 @@ pub fn part2(mut monkeys: Monkeys) -> Result<i64> { fn test() { assert_eq!( part1(parse(parse::data(2022, 11).unwrap()).unwrap()).unwrap(), - 0 + 51075 ); assert_eq!( part2(parse(parse::data(2022, 11).unwrap()).unwrap()).unwrap(), - 0 + 11741456163 ); } diff --git a/src/2022/2/mod.rs b/src/bin/2022/day2.rs index 5f173ac..03a5360 100644 --- a/src/2022/2/mod.rs +++ b/src/bin/2022/day2.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Copy, Clone, Eq, PartialEq)] enum Outcome { @@ -11,7 +11,7 @@ enum Outcome { } impl Outcome { - fn score(self) -> i64 { + fn score(self) -> u64 { match self { Self::Lose => 0, Self::Draw => 3, @@ -41,7 +41,7 @@ enum Shape { } impl Shape { - fn score(self) -> i64 { + fn score(self) -> u64 { match self { Self::Rock => 1, Self::Paper => 2, @@ -97,10 +97,10 @@ impl std::str::FromStr for Shape { } pub fn parse(fh: File) -> Result<impl Iterator<Item = String>> { - Ok(parse::lines(fh)) + Ok(parse::raw_lines(fh)) } -pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part1(lines: impl Iterator<Item = String>) -> Result<u64> { Ok(lines .map(|line| { let mut parts = line.split(' '); @@ -111,7 +111,7 @@ pub fn part1(lines: impl Iterator<Item = String>) -> Result<i64> { .sum()) } -pub fn part2(lines: impl Iterator<Item = String>) -> Result<i64> { +pub fn part2(lines: impl Iterator<Item = String>) -> Result<u64> { Ok(lines .map(|line| { let mut parts = line.split(' '); diff --git a/src/2022/3/mod.rs b/src/bin/2022/day3.rs index b6c339e..a56baf4 100644 --- a/src/2022/3/mod.rs +++ b/src/bin/2022/day3.rs @@ -1,12 +1,12 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse( fh: File, ) -> Result<impl Iterator<Item = (HashSet<char>, HashSet<char>)>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { let (first, second) = line.split_at(line.len() / 2); let first: HashSet<char> = first.chars().collect(); let second: HashSet<char> = second.chars().collect(); @@ -16,17 +16,17 @@ pub fn parse( pub fn part1( sacks: impl Iterator<Item = (HashSet<char>, HashSet<char>)>, -) -> Result<i64> { +) -> Result<u32> { Ok(sacks .map(|(first, second)| { - i64::from(priority(*first.intersection(&second).next().unwrap())) + priority(*first.intersection(&second).next().unwrap()) }) .sum()) } pub fn part2( mut sacks: impl Iterator<Item = (HashSet<char>, HashSet<char>)>, -) -> Result<i64> { +) -> Result<u32> { let mut total = 0; while let (Some(first), Some(second), Some(third)) = (sacks.next(), sacks.next(), sacks.next()) @@ -35,9 +35,8 @@ pub fn part2( let second: HashSet<char> = second.0.union(&second.1).copied().collect(); let third: HashSet<char> = third.0.union(&third.1).copied().collect(); - total += i64::from(priority( - *(&(&first & &second) & &third).iter().next().unwrap(), - )); + total += + priority(*(&(&first & &second) & &third).iter().next().unwrap()); } Ok(total) } diff --git a/src/2022/4/mod.rs b/src/bin/2022/day4.rs index 60aa353..2fe98c5 100644 --- a/src/2022/4/mod.rs +++ b/src/bin/2022/day4.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub struct Pair { first: (i64, i64), @@ -29,7 +29,7 @@ fn range_overlaps(a: (i64, i64), b: (i64, i64)) -> bool { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Pair>> { - Ok(parse::lines(fh).map(|line| { + Ok(parse::raw_lines(fh).map(|line| { let mut parts = line.split(','); let first = parts.next().unwrap(); let mut first_parts = first.split('-'); @@ -48,20 +48,12 @@ pub fn parse(fh: File) -> Result<impl Iterator<Item = Pair>> { })) } -pub fn part1(pairs: impl Iterator<Item = Pair>) -> Result<i64> { - Ok(pairs - .filter(|pair| pair.contains()) - .count() - .try_into() - .unwrap()) +pub fn part1(pairs: impl Iterator<Item = Pair>) -> Result<usize> { + Ok(pairs.filter(|pair| pair.contains()).count()) } -pub fn part2(pairs: impl Iterator<Item = Pair>) -> Result<i64> { - Ok(pairs - .filter(|pair| pair.overlaps()) - .count() - .try_into() - .unwrap()) +pub fn part2(pairs: impl Iterator<Item = Pair>) -> Result<usize> { + Ok(pairs.filter(|pair| pair.overlaps()).count()) } #[test] diff --git a/src/2022/5/mod.rs b/src/bin/2022/day5.rs index 74e4285..da1e5a2 100644 --- a/src/2022/5/mod.rs +++ b/src/bin/2022/day5.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Default)] pub struct Pile(Vec<char>); @@ -42,7 +42,7 @@ pub struct Crates { } pub fn parse(fh: File) -> Result<Crates> { - let mut lines = parse::lines(fh); + let mut lines = parse::raw_lines(fh); let mut piles: Vec<Pile> = vec![]; for line in lines.by_ref() { diff --git a/src/2022/6/mod.rs b/src/bin/2022/day6.rs index b736294..6fe154f 100644 --- a/src/2022/6/mod.rs +++ b/src/bin/2022/day6.rs @@ -1,25 +1,25 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<String> { Ok(parse::string(fh)) } -pub fn part1(s: String) -> Result<i64> { +pub fn part1(s: String) -> Result<usize> { for (i, slice) in s.as_bytes().windows(4).enumerate() { if slice.iter().copied().collect::<HashSet<u8>>().len() == 4 { - return Ok(i64::try_from(i).unwrap() + 4); + return Ok(i + 4); } } Err(anyhow!("couldn't find marker")) } -pub fn part2(s: String) -> Result<i64> { +pub fn part2(s: String) -> Result<usize> { for (i, slice) in s.as_bytes().windows(14).enumerate() { if slice.iter().copied().collect::<HashSet<u8>>().len() == 14 { - return Ok(i64::try_from(i).unwrap() + 14); + return Ok(i + 14); } } Err(anyhow!("couldn't find marker")) diff --git a/src/2022/7/mod.rs b/src/bin/2022/day7.rs index 9fbaf97..d0101c9 100644 --- a/src/2022/7/mod.rs +++ b/src/bin/2022/day7.rs @@ -1,11 +1,11 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub enum Node { Dir, - File(i64), + File(u64), } impl Node { @@ -13,11 +13,11 @@ impl Node { Self::Dir } - fn new_file(size: i64) -> Self { + fn new_file(size: u64) -> Self { Self::File(size) } - fn size(&self) -> i64 { + fn size(&self) -> u64 { match self { Self::Dir => 0, Self::File(size) => *size, @@ -25,12 +25,12 @@ impl Node { } } -fn tree_size(tree: &Tree<String, Node>) -> i64 { +fn tree_size(tree: &Tree<String, Node>) -> u64 { tree.bfs().map(|(_, tree)| tree.data().size()).sum() } pub fn parse(fh: File) -> Result<Tree<String, Node>> { - let mut lines = parse::lines(fh).peekable(); + let mut lines = parse::raw_lines(fh).peekable(); let mut root = Tree::new(Node::Dir); let mut path = vec![]; @@ -92,7 +92,7 @@ pub fn parse(fh: File) -> Result<Tree<String, Node>> { Ok(root) } -pub fn part1(tree: Tree<String, Node>) -> Result<i64> { +pub fn part1(tree: Tree<String, Node>) -> Result<u64> { let mut total = 0; for (_, tree) in tree.bfs() { if matches!(tree.data(), Node::File(_)) { @@ -106,7 +106,7 @@ pub fn part1(tree: Tree<String, Node>) -> Result<i64> { Ok(total) } -pub fn part2(tree: Tree<String, Node>) -> Result<i64> { +pub fn part2(tree: Tree<String, Node>) -> Result<u64> { let total = tree_size(&tree); let free = 70_000_000 - total; let needed = 30_000_000 - free; diff --git a/src/2022/8/mod.rs b/src/bin/2022/day8.rs index 49df9dd..6ec110e 100644 --- a/src/2022/8/mod.rs +++ b/src/bin/2022/day8.rs @@ -1,13 +1,13 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; pub fn parse(fh: File) -> Result<Grid<u8>> { - Ok(parse::digit_grid(parse::lines(fh))) + Ok(parse::digit_grid(parse::raw_lines(fh))) } -pub fn part1(trees: Grid<u8>) -> Result<i64> { +pub fn part1(trees: Grid<u8>) -> Result<u64> { let mut total = 0; for row in trees.each_row() { 'tree: for col in trees.each_col() { @@ -50,7 +50,7 @@ pub fn part1(trees: Grid<u8>) -> Result<i64> { Ok(total) } -pub fn part2(trees: Grid<u8>) -> Result<i64> { +pub fn part2(trees: Grid<u8>) -> Result<usize> { let mut max = 0; for row in trees.each_row() { for col in trees.each_col() { @@ -140,7 +140,7 @@ pub fn part2(trees: Grid<u8>) -> Result<i64> { } } } - Ok(max.try_into().unwrap()) + Ok(max) } #[test] diff --git a/src/2022/9/mod.rs b/src/bin/2022/day9.rs index f075224..235ec44 100644 --- a/src/2022/9/mod.rs +++ b/src/bin/2022/day9.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -use crate::prelude::*; +use advent_of_code::prelude::*; #[derive(Debug)] enum Direction { @@ -190,10 +190,10 @@ impl Map { } pub fn parse(fh: File) -> Result<impl Iterator<Item = Move>> { - Ok(parse::lines(fh).map(|line| Move::parse(&line))) + Ok(parse::raw_lines(fh).map(|line| Move::parse(&line))) } -pub fn part1(moves: impl Iterator<Item = Move>) -> Result<i64> { +pub fn part1(moves: impl Iterator<Item = Move>) -> Result<usize> { let mut map = Map::new(2); for mv in moves { // println!("{:?}", map); @@ -205,12 +205,10 @@ pub fn part1(moves: impl Iterator<Item = Move>) -> Result<i64> { .iter() .flat_map(|row| row.iter().copied()) .filter(|cell| *cell) - .count() - .try_into() - .unwrap()) + .count()) } -pub fn part2(moves: impl Iterator<Item = Move>) -> Result<i64> { +pub fn part2(moves: impl Iterator<Item = Move>) -> Result<usize> { let mut map = Map::new(10); for mv in moves { // println!("{:?}", map); @@ -222,9 +220,7 @@ pub fn part2(moves: impl Iterator<Item = Move>) -> Result<i64> { .iter() .flat_map(|row| row.iter().copied()) .filter(|cell| *cell) - .count() - .try_into() - .unwrap()) + .count()) } #[test] diff --git a/src/bin/2022/main.rs b/src/bin/2022/main.rs new file mode 100644 index 0000000..09a9248 --- /dev/null +++ b/src/bin/2022/main.rs @@ -0,0 +1,46 @@ +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::similar_names)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::type_complexity)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::collapsible_if)] +#![allow(clippy::comparison_chain)] + +use advent_of_code::prelude::*; + +mod day1; +mod day10; +mod day11; +mod day2; +mod day3; +mod day4; +mod day5; +mod day6; +mod day7; +mod day8; +mod day9; +// NEXT MOD + +#[paw::main] +fn main(opt: Opt) -> Result<()> { + #[allow(clippy::match_single_binding)] + match opt.day { + 1 => advent_of_code::day!(2022, opt.day, opt.puzzle, day1), + 2 => advent_of_code::day!(2022, opt.day, opt.puzzle, day2), + 3 => advent_of_code::day!(2022, opt.day, opt.puzzle, day3), + 4 => advent_of_code::day!(2022, opt.day, opt.puzzle, day4), + 5 => advent_of_code::day!(2022, opt.day, opt.puzzle, day5), + 6 => advent_of_code::day!(2022, opt.day, opt.puzzle, day6), + 7 => advent_of_code::day!(2022, opt.day, opt.puzzle, day7), + 8 => advent_of_code::day!(2022, opt.day, opt.puzzle, day8), + 9 => advent_of_code::day!(2022, opt.day, opt.puzzle, day9), + 10 => advent_of_code::day!(2022, opt.day, opt.puzzle, day10), + 11 => advent_of_code::day!(2022, opt.day, opt.puzzle, day11), + // NEXT PART + _ => panic!("unknown day {}", opt.day), + } + Ok(()) +} diff --git a/src/graph.rs b/src/graph.rs index 831cc17..74c2910 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -7,9 +7,9 @@ where type Edges: IntoIterator<Item = Edge>; fn edges(&self, v: Vertex) -> Self::Edges; - fn edge(&self, v: Vertex, e: Edge) -> (Vertex, i64); + fn edge(&self, v: Vertex, e: Edge) -> (Vertex, u64); - fn dijkstra(&self, start: Vertex, end: Vertex) -> (i64, Vec<Vertex>) { + fn dijkstra(&self, start: Vertex, end: Vertex) -> (u64, Vec<Vertex>) { let mut to_visit = priority_queue::PriorityQueue::new(); let mut prev = HashMap::new(); prev.insert(start, start); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..16bba29 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,18 @@ +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::similar_names)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::type_complexity)] +#![allow(clippy::collapsible_else_if)] +#![allow(clippy::collapsible_if)] +#![allow(clippy::comparison_chain)] + +pub mod graph; +pub mod grid; +pub mod opt; +pub mod parse; +pub mod prelude; +pub mod regex; +pub mod tree; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 490fa02..0000000 --- a/src/main.rs +++ /dev/null @@ -1,55 +0,0 @@ -#![allow(clippy::cognitive_complexity)] -#![allow(clippy::missing_const_for_fn)] -#![allow(clippy::similar_names)] -#![allow(clippy::struct_excessive_bools)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] -#![allow(clippy::type_complexity)] -#![allow(clippy::collapsible_else_if)] -#![allow(clippy::collapsible_if)] -#![allow(clippy::comparison_chain)] - -#[macro_use] -pub mod regex; - -pub mod graph; -pub mod grid; -pub mod parse; -pub mod prelude; -pub mod tree; - -#[path = "2020/mod.rs"] -mod year2020; -#[path = "2021/mod.rs"] -mod year2021; -#[path = "2022/mod.rs"] -mod year2022; - -#[derive(Debug, structopt::StructOpt)] -#[structopt(about = "Advent of Code")] -enum Opt { - #[structopt(name = "2020")] - Year2020 { day: u8, puzzle: u8 }, - #[structopt(name = "2021")] - Year2021 { day: u8, puzzle: u8 }, - #[structopt(name = "2022")] - Year2022 { day: u8, puzzle: u8 }, -} - -#[paw::main] -fn main(opt: Opt) { - let res = match opt { - Opt::Year2020 { day, puzzle } => crate::year2020::run(day, puzzle), - Opt::Year2021 { day, puzzle } => crate::year2021::run(day, puzzle), - Opt::Year2022 { day, puzzle } => crate::year2022::run(day, puzzle), - }; - match res { - Ok(answer) => { - println!("{}", answer); - } - Err(e) => { - eprintln!("{}", e); - std::process::exit(1); - } - } -} diff --git a/src/opt.rs b/src/opt.rs new file mode 100644 index 0000000..296ea83 --- /dev/null +++ b/src/opt.rs @@ -0,0 +1,20 @@ +#[derive(Debug, structopt::StructOpt)] +#[structopt(about = "Advent of Code")] +pub struct Opt { + pub day: u8, + pub puzzle: u8, +} + +#[macro_export] +macro_rules! day { + ($year:expr, $day:expr, $puzzle:expr, $mod:ident) => {{ + let data = $mod::parse(parse::data($year, $day)?)?; + match $puzzle { + 1 => println!("{}", $mod::part1(data)?), + 2 => println!("{}", $mod::part2(data)?), + _ => { + panic!("unknown puzzle {} for day {}", $puzzle, $day) + } + } + }}; +} diff --git a/src/parse.rs b/src/parse.rs index 3222bf0..7e6cab7 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,14 +1,26 @@ use crate::prelude::*; -pub fn data(year: u16, day: u16) -> Result<File> { +pub fn data(year: u16, day: u8) -> Result<File> { File::open(format!("data/{}/{}.txt", year, day)).map_err(|e| anyhow!(e)) } -pub fn lines<R: std::io::Read>(fh: R) -> impl Iterator<Item = String> { +pub fn raw_lines<R>(fh: R) -> impl Iterator<Item = String> +where + R: std::io::Read, +{ let fh = std::io::BufReader::new(fh); fh.lines().map(|res| res.unwrap()) } +pub fn lines<R, T>(fh: R) -> impl Iterator<Item = T> +where + R: std::io::Read, + T: std::str::FromStr, + <T as std::str::FromStr>::Err: std::fmt::Debug, +{ + raw_lines(fh).map(|s| s.trim().parse().unwrap()) +} + pub struct Chunk<'a, I: Iterator<Item = String>> { it: &'a mut I, } @@ -35,17 +47,16 @@ where Chunk { it } } -pub fn split<R: std::io::Read>( - fh: R, - sep: u8, -) -> impl Iterator<Item = String> { +pub fn split<R, T>(fh: R, sep: u8) -> impl Iterator<Item = T> +where + R: std::io::Read, + T: std::str::FromStr, + <T as std::str::FromStr>::Err: std::fmt::Debug, +{ let fh = std::io::BufReader::new(fh); fh.split(sep) .map(|res| String::from_utf8(res.unwrap()).unwrap()) -} - -pub fn ints(iter: impl Iterator<Item = String>) -> impl Iterator<Item = i64> { - iter.map(|s| s.trim().parse().unwrap()) + .map(|s| s.trim().parse().unwrap()) } pub fn bytes<R: std::io::Read>(fh: R) -> impl Iterator<Item = u8> { diff --git a/src/prelude.rs b/src/prelude.rs index 046b4fb..46a7ee5 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,6 +1,8 @@ pub use crate::graph::Graph as _; pub use crate::grid::{Col, Grid, Row}; +pub use crate::opt::Opt; pub use crate::parse; +pub use crate::regex_captures; pub use crate::tree::Tree; pub use std::cmp::Ordering; diff --git a/src/regex.rs b/src/regex.rs index 12f8876..5e38c81 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -1,3 +1,4 @@ +#[macro_export] macro_rules! regex_captures { ($rx:expr, $s:expr $(,)?) => {{ static RX: once_cell::sync::Lazy<regex::Regex> = |