summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-12-11 21:59:21 -0500
committerJesse Luehrs <doy@tozt.net>2022-12-11 22:16:30 -0500
commite2d219b331a878bbb3c9dcef9ea4e218b2e3ee06 (patch)
tree93e418011c45cab8d4070d3d33b377a9364f4a27
parent179467096141b7e8f67d63b89fd21e779a564fe6 (diff)
downloadadvent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.tar.gz
advent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.zip
refactor
-rwxr-xr-xbin/stub-code9
-rw-r--r--src/2020/mod.rs47
-rw-r--r--src/2021/mod.rs111
-rw-r--r--src/2022/mod.rs55
-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.rs42
-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.rs74
-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.rs46
-rw-r--r--src/graph.rs4
-rw-r--r--src/lib.rs18
-rw-r--r--src/main.rs55
-rw-r--r--src/opt.rs20
-rw-r--r--src/parse.rs31
-rw-r--r--src/prelude.rs2
-rw-r--r--src/regex.rs1
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> =