diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 761f96e..6309f5b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,7 +14,7 @@ concurrency: cancel-in-progress: true env: - MSRV: "1.74" + MSRV: "1.75" CARGO_TERM_COLOR: always jobs: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e58642..73e230b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,22 +26,17 @@ repos: - id: beautysh - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.3.0 hooks: - id: codespell args: ["--ignore-words-list", "crate"] exclude: Cargo.lock|input/.*|aoc2023/.*/day15.rs - repo: https://github.com/hadolint/hadolint - rev: v2.12.1-beta + rev: v2.13.1-beta hooks: - id: hadolint-docker - - repo: https://github.com/executablebooks/mdformat - rev: 0.7.17 - hooks: - - id: mdformat - - repo: https://github.com/AndrejOrsula/pre-commit-cargo rev: 0.3.0 hooks: diff --git a/Dockerfile b/Dockerfile index c8940bb..441173c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG RUST_VERSION=1.74 +ARG RUST_VERSION=latest FROM rust:${RUST_VERSION} ### Use bash as the default shell diff --git a/README.md b/README.md index c2fb39c..202dd8b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ My solutions to [Advent of Code](https://adventofcode.com) puzzles. ## Edition -### [Advent of Code 2023](https://adventofcode.com/2023) +

Advent of Code 2023

> All benchmarks are run on a *Dell Precision 5550* laptop with an *Intel Core i7-10875H* CPU. @@ -105,10 +105,11 @@ My solutions to [Advent of Code](https://adventofcode.com) puzzles. | 252.4 µs | 61.18 ms | | 101.2 µs | 2.5839 s | | 79.73 µs | 2.4001 s | -| 0.000 µs | 0.000 µs | +| — | — | +
## Instructions diff --git a/aoc2023/Cargo.toml b/aoc2023/Cargo.toml index 89d452f..494f9a2 100644 --- a/aoc2023/Cargo.toml +++ b/aoc2023/Cargo.toml @@ -2,21 +2,22 @@ name = "aoc2023" description = "Advent of Code 2023" edition = "2021" -rust-version = "1.74" +rust-version = "1.75" version = "0.1.0" authors.workspace = true keywords.workspace = true license.workspace = true readme.workspace = true repository.workspace = true +publish = false [dependencies] aoc-runner = { workspace = true } aoc-runner-derive = { workspace = true } indoc = { workspace = true } -derive_more = { version = "0.99" } -itertools = { version = "0.12" } +derive_more = { version = "1", features = ["full"] } +itertools = { version = "0.13" } num = { version = "0.4" } num-integer = { version = "0.1" } pathfinding = { version = "4.4" } diff --git a/aoc2023/src/day1.rs b/aoc2023/src/day1.rs index ac6526e..f8143c1 100644 --- a/aoc2023/src/day1.rs +++ b/aoc2023/src/day1.rs @@ -1,12 +1,8 @@ -use aoc_runner_derive::{aoc, aoc_generator}; - -#[aoc_generator(day1)] -fn parse(input: &str) -> String { - input.to_owned() -} +use aoc_runner_derive::aoc; #[aoc(day1, part1)] -fn part1(input: &str) -> u32 { +#[must_use] +pub fn part1(input: &str) -> u32 { input .lines() .map(|line| { @@ -20,7 +16,8 @@ fn part1(input: &str) -> u32 { } #[aoc(day1, part2)] -fn part2(input: &str) -> u32 { +#[must_use] +pub fn part2(input: &str) -> u32 { input .lines() .map(|line| { @@ -149,18 +146,18 @@ mod tests { use indoc::indoc; #[test] - fn part1_example() { + pub fn part1_example() { const SAMPLE: &str = indoc! {" 1abc2 pqr3stu8vwx a1b2c3d4e5f treb7uchet "}; - assert_eq!(part1(&parse(SAMPLE)), 142); + assert_eq!(part1(SAMPLE), 142); } #[test] - fn part2_example() { + pub fn part2_example() { const SAMPLE: &str = indoc! {" two1nine eightwothree @@ -170,6 +167,6 @@ mod tests { zoneight234 7pqrstsixteen "}; - assert_eq!(part2(&parse(SAMPLE)), 281); + assert_eq!(part2(SAMPLE), 281); } } diff --git a/aoc2023/src/day10.rs b/aoc2023/src/day10.rs index 6162188..2c8282f 100644 --- a/aoc2023/src/day10.rs +++ b/aoc2023/src/day10.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day10)] fn parse(input: &str) -> utils::Map { let mut grid = pathfinding::matrix::Matrix::new( input.lines().count(), @@ -25,13 +24,17 @@ fn parse(input: &str) -> utils::Map { } #[aoc(day10, part1)] -fn part1(input: &utils::Map) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); // The furthest point from the start is always the middle of the loop input.get_loop().len() / 2 } #[aoc(day10, part2)] -fn part2(input: &utils::Map) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); // Construct a grid that only contains the loop let mut enclosure = pathfinding::matrix::Matrix::new(input.grid.rows, input.grid.columns, utils::Tile::Ground); @@ -174,7 +177,7 @@ mod tests { use indoc::indoc; #[test] - fn part1_example() { + pub fn part1_example() { const SAMPLES: [&str; 2] = [ indoc! {" ..... @@ -192,12 +195,12 @@ mod tests { "}, ]; - assert_eq!(part1(&parse(SAMPLES[0])), 4); - assert_eq!(part1(&parse(SAMPLES[1])), 8); + assert_eq!(part1(SAMPLES[0]), 4); + assert_eq!(part1(SAMPLES[1]), 8); } #[test] - fn part2_example() { + pub fn part2_example() { const SAMPLES: [&str; 3] = [ indoc! {" ........... @@ -236,8 +239,8 @@ mod tests { "}, ]; - assert_eq!(part2(&parse(SAMPLES[0])), 4); - assert_eq!(part2(&parse(SAMPLES[1])), 8); - assert_eq!(part2(&parse(SAMPLES[2])), 10); + assert_eq!(part2(SAMPLES[0]), 4); + assert_eq!(part2(SAMPLES[1]), 8); + assert_eq!(part2(SAMPLES[2]), 10); } } diff --git a/aoc2023/src/day11.rs b/aoc2023/src/day11.rs index e319bc4..410281b 100644 --- a/aoc2023/src/day11.rs +++ b/aoc2023/src/day11.rs @@ -1,23 +1,25 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day11, part1)] fn parse1(input: &str) -> Vec<(usize, usize)> { utils::parse_expanded_galaxies(input, 1) } -#[aoc_generator(day11, part2)] fn parse2(input: &str) -> Vec<(usize, usize)> { utils::parse_expanded_galaxies(input, 999_999) } #[aoc(day11, part1)] -fn part1(input: &[(usize, usize)]) -> usize { - utils::sum_galactic_distances(input) +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse1(input); + utils::sum_galactic_distances(&input) } #[aoc(day11, part2)] -fn part2(input: &[(usize, usize)]) -> usize { - utils::sum_galactic_distances(input) +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse2(input); + utils::sum_galactic_distances(&input) } mod utils { @@ -133,13 +135,19 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse1(SAMPLE)), 374); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 374); } #[test] - fn part2_example() { - assert_eq!(part2(&utils::parse_expanded_galaxies(SAMPLE, 9)), 1030); - assert_eq!(part2(&utils::parse_expanded_galaxies(SAMPLE, 99)), 8410); + pub fn part2_example() { + assert_eq!( + utils::sum_galactic_distances(&utils::parse_expanded_galaxies(SAMPLE, 9)), + 1030 + ); + assert_eq!( + utils::sum_galactic_distances(&utils::parse_expanded_galaxies(SAMPLE, 99)), + 8410 + ); } } diff --git a/aoc2023/src/day12.rs b/aoc2023/src/day12.rs index 5f32ca4..f656dbf 100644 --- a/aoc2023/src/day12.rs +++ b/aoc2023/src/day12.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day12)] fn parse(input: &str) -> Vec { input .lines() @@ -19,7 +18,8 @@ fn parse(input: &str) -> Vec { } #[aoc(day12, part1)] -fn part1(input: &[utils::SpringSequence]) -> usize { +pub fn part1(input: &str) -> usize { + let input = parse(input); input .iter() .map(utils::SpringSequence::discover_arrangements) @@ -27,7 +27,9 @@ fn part1(input: &[utils::SpringSequence]) -> usize { } #[aoc(day12, part2)] -fn part2(input: &[utils::SpringSequence]) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); input .iter() .map(|sequence| { @@ -155,12 +157,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 21); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 21); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 525_152); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 525_152); } } diff --git a/aoc2023/src/day13.rs b/aoc2023/src/day13.rs index 1c5be80..e3741ca 100644 --- a/aoc2023/src/day13.rs +++ b/aoc2023/src/day13.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day13)] fn parse(input: &str) -> Vec { input .split("\n\n") @@ -9,7 +8,9 @@ fn parse(input: &str) -> Vec { } #[aoc(day13, part1)] -fn part1(input: &[utils::Pattern]) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); input .iter() .map(|pattern| { @@ -19,9 +20,11 @@ fn part1(input: &[utils::Pattern]) -> usize { } #[aoc(day13, part2)] -fn part2(input: &[utils::Pattern]) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { use rayon::prelude::*; + let input = parse(input); input .iter() .par_bridge() @@ -99,12 +102,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 405); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 405); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 400); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 400); } } diff --git a/aoc2023/src/day14.rs b/aoc2023/src/day14.rs index e466852..bc03baa 100644 --- a/aoc2023/src/day14.rs +++ b/aoc2023/src/day14.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day14)] fn parse(input: &str) -> utils::Platform { let mut matrix = pathfinding::matrix::Matrix::new( input.lines().count(), @@ -16,17 +15,19 @@ fn parse(input: &str) -> utils::Platform { } #[aoc(day14, part1)] -fn part1(input: &utils::Platform) -> usize { - let mut input = input.clone(); +#[must_use] +pub fn part1(input: &str) -> usize { + let mut input = parse(input); input.slide_rocks_north(); input.compute_load() } #[aoc(day14, part2)] -fn part2(input: &utils::Platform) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { const TARGET_N_SPINS: usize = 1_000_000_000; - let mut input = input.clone(); + let mut input = parse(input); let mut visited: rustc_hash::FxHashMap = [(input.clone(), 0)].into_iter().collect(); @@ -153,12 +154,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 136); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 136); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 64); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 64); } } diff --git a/aoc2023/src/day15.rs b/aoc2023/src/day15.rs index 6b029eb..1cbc4fd 100644 --- a/aoc2023/src/day15.rs +++ b/aoc2023/src/day15.rs @@ -1,20 +1,23 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day15)] fn parse(input: &str) -> Vec { input.split(',').map(|x| x.trim().to_owned()).collect() } #[aoc(day15, part1)] -fn part1(input: &[String]) -> u32 { +#[must_use] +pub fn part1(input: &str) -> u32 { + let input = parse(input); input.iter().map(|step| u32::from(utils::hash(step))).sum() } #[aoc(day15, part2)] -fn part2(input: &[String]) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); let mut boxes = vec![smallvec::SmallVec::<[_; 5]>::new(); 256]; - for step in input { - let (label, focal_length) = step.split_once(|c| c == '=' || c == '-').unwrap(); + for step in &input { + let (label, focal_length) = step.split_once(['=', '-']).unwrap(); let current_box = boxes.get_mut(utils::hash(label) as usize).unwrap(); let slot_index = current_box.iter().position(|&(l, _)| l == label); if step.contains('=') { @@ -63,12 +66,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 1320); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 1320); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 145); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 145); } } diff --git a/aoc2023/src/day16.rs b/aoc2023/src/day16.rs index f570303..252daf6 100644 --- a/aoc2023/src/day16.rs +++ b/aoc2023/src/day16.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day16)] fn parse(input: &str) -> utils::Cave { let mut matrix = pathfinding::matrix::Matrix::new( input.lines().count(), @@ -16,15 +15,19 @@ fn parse(input: &str) -> utils::Cave { } #[aoc(day16, part1)] -fn part1(input: &utils::Cave) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); let beam = utils::Beam::new((0, 0), utils::Direction::East); input.get_energized_tiles(beam).len() } #[aoc(day16, part2)] -fn part2(input: &utils::Cave) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { use rayon::prelude::*; + let input = parse(input); (0..input.columns) .map(|x| utils::Beam::new((x, 0), utils::Direction::South)) .chain( @@ -181,12 +184,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 46); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 46); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 51); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 51); } } diff --git a/aoc2023/src/day17.rs b/aoc2023/src/day17.rs index abb0fd0..7a6718f 100644 --- a/aoc2023/src/day17.rs +++ b/aoc2023/src/day17.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day17)] fn parse(input: &str) -> utils::Map { let mut matrix = pathfinding::matrix::Matrix::new( input.lines().count(), @@ -16,12 +15,16 @@ fn parse(input: &str) -> utils::Map { } #[aoc(day17, part1)] -fn part1(input: &utils::Map) -> u32 { +#[must_use] +pub fn part1(input: &str) -> u32 { + let input = parse(input); input.find_shortest_path(0, 3) } #[aoc(day17, part2)] -fn part2(input: &utils::Map) -> u32 { +#[must_use] +pub fn part2(input: &str) -> u32 { + let input = parse(input); input.find_shortest_path(4, 10) } @@ -191,12 +194,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 102); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 102); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 94); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 94); } } diff --git a/aoc2023/src/day18.rs b/aoc2023/src/day18.rs index 12a7dfb..8c780b6 100644 --- a/aoc2023/src/day18.rs +++ b/aoc2023/src/day18.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day18, part1)] fn parse1(input: &str) -> Vec<(utils::Direction, u32)> { use itertools::Itertools; @@ -16,7 +15,6 @@ fn parse1(input: &str) -> Vec<(utils::Direction, u32)> { .collect() } -#[aoc_generator(day18, part2)] fn parse2(input: &str) -> Vec<(utils::Direction, u32)> { use itertools::Itertools; @@ -38,13 +36,17 @@ fn parse2(input: &str) -> Vec<(utils::Direction, u32)> { } #[aoc(day18, part1)] -fn part1(input: &[(utils::Direction, u32)]) -> u64 { - utils::compute_area(input) +#[must_use] +pub fn part1(input: &str) -> u64 { + let input = parse1(input); + utils::compute_area(&input) } #[aoc(day18, part2)] -fn part2(input: &[(utils::Direction, u32)]) -> u64 { - utils::compute_area(input) +#[must_use] +pub fn part2(input: &str) -> u64 { + let input = parse2(input); + utils::compute_area(&input) } mod utils { @@ -116,12 +118,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse1(SAMPLE)), 62); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 62); } #[test] - fn part2_example() { - assert_eq!(part2(&parse2(SAMPLE)), 952_408_144_115); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 952_408_144_115); } } diff --git a/aoc2023/src/day19.rs b/aoc2023/src/day19.rs index ccc192e..f81155d 100644 --- a/aoc2023/src/day19.rs +++ b/aoc2023/src/day19.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day19)] fn parse(input: &str) -> utils::SortingSystem { let (workflows, part_ratings) = input.split_once("\n\n").unwrap(); @@ -61,12 +60,16 @@ fn parse(input: &str) -> utils::SortingSystem { } #[aoc(day19, part1)] -fn part1(input: &utils::SortingSystem) -> u64 { - utils::count_accepted(input, "in") +#[must_use] +pub fn part1(input: &str) -> u64 { + let input = parse(input); + utils::count_accepted(&input, "in") } #[aoc(day19, part2)] -fn part2(input: &utils::SortingSystem) -> u64 { +#[must_use] +pub fn part2(input: &str) -> u64 { + let input = parse(input); use strum::IntoEnumIterator; utils::count_all_accepted_combinations_recursively( &input.workflows, @@ -262,12 +265,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 19114); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 19114); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 167_409_079_868_000); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 167_409_079_868_000); } } diff --git a/aoc2023/src/day2.rs b/aoc2023/src/day2.rs index 715d95c..c19c519 100644 --- a/aoc2023/src/day2.rs +++ b/aoc2023/src/day2.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day2)] fn parse(input: &str) -> Vec { use std::str::FromStr; @@ -39,11 +38,13 @@ fn parse(input: &str) -> Vec { } #[aoc(day2, part1)] -fn part1(input: &[utils::Game]) -> u32 { +#[must_use] +pub fn part1(input: &str) -> u32 { const MAX_N_RED: u8 = 12; const MAX_N_GREEN: u8 = 13; const MAX_N_BLUE: u8 = 14; + let input = parse(input); input .iter() .filter_map(|game| { @@ -65,7 +66,9 @@ fn part1(input: &[utils::Game]) -> u32 { } #[aoc(day2, part2)] -fn part2(input: &[utils::Game]) -> u32 { +#[must_use] +pub fn part2(input: &str) -> u32 { + let input = parse(input); input .iter() .map(|game| { @@ -92,6 +95,7 @@ mod utils { } #[derive(Default)] + #[allow(clippy::struct_field_names)] pub struct CubeSet { pub n_red: u8, pub n_green: u8, @@ -141,12 +145,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 8); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 8); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 2286); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 2286); } } diff --git a/aoc2023/src/day20.rs b/aoc2023/src/day20.rs index 203cb38..231cc21 100644 --- a/aoc2023/src/day20.rs +++ b/aoc2023/src/day20.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day20)] fn parse(input: &str) -> utils::Modules { let mut modules: rustc_hash::FxHashMap = input .lines() @@ -48,8 +47,9 @@ fn parse(input: &str) -> utils::Modules { } #[aoc(day20, part1)] -fn part1(input: &utils::Modules) -> usize { - let mut input = input.clone(); +#[must_use] +pub fn part1(input: &str) -> usize { + let mut input = parse(input); let (n_low, n_high) = (0..1000).fold((0, 0), |(mut acc_low, mut acc_high), _| { let mut active_pulses = std::collections::VecDeque::default(); @@ -80,8 +80,9 @@ fn part1(input: &utils::Modules) -> usize { } #[aoc(day20, part2)] -fn part2(input: &utils::Modules) -> usize { - let mut input = input.clone(); +#[must_use] +pub fn part2(input: &str) -> usize { + let mut input = parse(input); // Find all modules that branch into a conjunction that is connected to the final "rx" module let mut final_module_sources = vec!["rx".to_string()]; @@ -260,12 +261,12 @@ mod tests { ]; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLES[0])), 32_000_000); - assert_eq!(part1(&parse(SAMPLES[1])), 11_687_500); + pub fn part1_example() { + assert_eq!(part1(SAMPLES[0]), 32_000_000); + assert_eq!(part1(SAMPLES[1]), 11_687_500); } #[test] #[ignore] - fn part2_example() {} + pub fn part2_example() {} } diff --git a/aoc2023/src/day21.rs b/aoc2023/src/day21.rs index 357ce62..9f5186f 100644 --- a/aoc2023/src/day21.rs +++ b/aoc2023/src/day21.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day21)] fn parse(input: &str) -> utils::Map { let mut grid = pathfinding::grid::Grid::new(input.lines().count(), input.lines().next().unwrap().len()); @@ -25,12 +24,16 @@ fn parse(input: &str) -> utils::Map { } #[aoc(day21, part1)] -fn part1(input: &utils::Map) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); input.count_reachable_plots(64, false) } #[aoc(day21, part2)] -fn part2(input: &utils::Map) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); input.count_reachable_plots2(26_501_365) } @@ -248,12 +251,12 @@ mod tests { "}; #[test] - fn part1_example() { + pub fn part1_example() { assert_eq!(parse(SAMPLE).count_reachable_plots(6, false), 16); } #[test] - fn part2_example() { + pub fn part2_example() { assert_eq!(parse(SAMPLE).count_reachable_plots(6, true), 16); assert_eq!(parse(SAMPLE).count_reachable_plots(10, true), 50); assert_eq!(parse(SAMPLE).count_reachable_plots(50, true), 1594); diff --git a/aoc2023/src/day22.rs b/aoc2023/src/day22.rs index 982e790..2abd209 100644 --- a/aoc2023/src/day22.rs +++ b/aoc2023/src/day22.rs @@ -1,7 +1,6 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; /// Parsed bricks are already settled on the ground and sorted by their Z coordinate. -#[aoc_generator(day22)] fn parse(input: &str) -> utils::Brickfall { use itertools::Itertools; use std::str::FromStr; @@ -17,14 +16,18 @@ fn parse(input: &str) -> utils::Brickfall { } #[aoc(day22, part1)] -fn part1(input: &utils::Brickfall) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); (0..input.len()) .filter(|&i| input.bricks_affected_by(i).all(|x| !x)) .count() } #[aoc(day22, part2)] -fn part2(input: &utils::Brickfall) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); (0..input.len()) .map(|i| input.bricks_affected_by(i).filter(|&x| x).count()) .sum() @@ -155,12 +158,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 5); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 5); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 7); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 7); } } diff --git a/aoc2023/src/day23.rs b/aoc2023/src/day23.rs index 8a5efa1..5e7de3a 100644 --- a/aoc2023/src/day23.rs +++ b/aoc2023/src/day23.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day23)] fn parse(input: &str) -> utils::Map { let mut matrix = pathfinding::matrix::Matrix::new( input.lines().count(), @@ -22,12 +21,16 @@ fn parse(input: &str) -> utils::Map { } #[aoc(day23, part1)] -fn part1(input: &utils::Map) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); input.longest_path_len(true) } #[aoc(day23, part2)] -fn part2(input: &utils::Map) -> usize { +#[must_use] +pub fn part2(input: &str) -> usize { + let input = parse(input); input.longest_path_len(false) } @@ -231,12 +234,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 94); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 94); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 154); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 154); } } diff --git a/aoc2023/src/day24.rs b/aoc2023/src/day24.rs index 304d923..bc3d3c6 100644 --- a/aoc2023/src/day24.rs +++ b/aoc2023/src/day24.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day24)] fn parse(input: &str) -> utils::Hail { use itertools::Itertools; input @@ -24,7 +23,9 @@ fn parse(input: &str) -> utils::Hail { } #[aoc(day24, part1)] -fn part1(input: &utils::Hail) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); input.count_intersections((200_000_000_000_000, 400_000_000_000_000)) } @@ -34,9 +35,12 @@ fn part1(input: &utils::Hail) -> usize { #[aoc(day24, part2)] #[allow(clippy::similar_names)] #[cfg(feature = "z3")] -fn part2(input: &utils::Hail) -> u64 { +#[must_use] +pub fn part2(input: &str) -> u64 { use z3::ast::Ast; + let input = parse(input); + let context = z3::Context::new(&z3::Config::default()); let solver = z3::Solver::new(&context); @@ -158,13 +162,13 @@ mod tests { "}; #[test] - fn part1_example() { + pub fn part1_example() { assert_eq!(parse(SAMPLE).count_intersections((7, 27)), 2); } #[test] #[cfg(feature = "z3")] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 47); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 47); } } diff --git a/aoc2023/src/day25.rs b/aoc2023/src/day25.rs index f7b68db..bdf254b 100644 --- a/aoc2023/src/day25.rs +++ b/aoc2023/src/day25.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day25)] fn parse(input: &str) -> petgraph::Graph { let mut graph = petgraph::Graph::default(); let mut nodes = std::collections::HashMap::new(); @@ -22,7 +21,9 @@ fn parse(input: &str) -> petgraph::Graph { } #[aoc(day25, part1)] -fn part1(input: &petgraph::Graph) -> usize { +#[must_use] +pub fn part1(input: &str) -> usize { + let input = parse(input); let min_cut_res: Result<_, ()> = rustworkx_core::connectivity::stoer_wagner_min_cut(&input, |_| Ok(1)); let (min_cut, partition) = min_cut_res.unwrap().unwrap(); @@ -39,7 +40,7 @@ mod tests { use indoc::indoc; #[test] - fn part1_example() { + pub fn part1_example() { const SAMPLE: &str = indoc! {" jqt: rhn xhk nvd rsh: frs pzl lsr @@ -56,6 +57,6 @@ mod tests { frs: qnr lhk lsr "}; - assert_eq!(part1(&parse(SAMPLE)), 54); + assert_eq!(part1(SAMPLE), 54); } } diff --git a/aoc2023/src/day3.rs b/aoc2023/src/day3.rs index afaa6d8..71d28cd 100644 --- a/aoc2023/src/day3.rs +++ b/aoc2023/src/day3.rs @@ -1,12 +1,7 @@ -use aoc_runner_derive::{aoc, aoc_generator}; - -#[aoc_generator(day3)] -fn parse(input: &str) -> String { - input.to_owned() -} +use aoc_runner_derive::aoc; #[aoc(day3, part1)] -fn part1(input: &str) -> u32 { +pub fn part1(input: &str) -> u32 { // Sum of all numbers that are surrounded by symbols let mut sum = 0; @@ -79,7 +74,7 @@ fn part1(input: &str) -> u32 { } #[aoc(day3, part2)] -fn part2(input: &str) -> u32 { +pub fn part2(input: &str) -> u32 { // Sum of all products between two numbers that are connected by a gear ('*') let mut sum = 0; @@ -225,12 +220,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 4361); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 4361); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 467_835); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 467_835); } } diff --git a/aoc2023/src/day4.rs b/aoc2023/src/day4.rs index 6d0b5c9..0c7010c 100644 --- a/aoc2023/src/day4.rs +++ b/aoc2023/src/day4.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day4)] fn parse(input: &str) -> Vec { input .lines() @@ -27,7 +26,9 @@ fn parse(input: &str) -> Vec { } #[aoc(day4, part1)] -fn part1(input: &[utils::Card]) -> u32 { +#[must_use] +pub fn part1(input: &str) -> u32 { + let input = parse(input); input .iter() .map(|card| match card.get_n_matches() { @@ -38,7 +39,9 @@ fn part1(input: &[utils::Card]) -> u32 { } #[aoc(day4, part2)] -fn part2(input: &[utils::Card]) -> u32 { +#[must_use] +pub fn part2(input: &str) -> u32 { + let input = parse(input); let mut card_count: Vec = vec![1; input.len()]; input .iter() @@ -88,12 +91,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 13); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 13); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 30); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 30); } } diff --git a/aoc2023/src/day5.rs b/aoc2023/src/day5.rs index ad93c41..ca1fed3 100644 --- a/aoc2023/src/day5.rs +++ b/aoc2023/src/day5.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day5)] fn parse(input: &str) -> utils::Almanac { use itertools::Itertools; @@ -40,7 +39,9 @@ fn parse(input: &str) -> utils::Almanac { } #[aoc(day5, part1)] -fn part1(input: &utils::Almanac) -> u64 { +#[must_use] +pub fn part1(input: &str) -> u64 { + let input = parse(input); let utils::Almanac { seeds, mappings } = input; seeds .iter() @@ -59,7 +60,9 @@ fn part1(input: &utils::Almanac) -> u64 { } #[aoc(day5, part2)] -fn part2(input: &utils::Almanac) -> u64 { +#[must_use] +pub fn part2(input: &str) -> u64 { + let input = parse(input); let utils::Almanac { seeds, mappings } = input; seeds .chunks(2) @@ -196,12 +199,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 35); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 35); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 46); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 46); } } diff --git a/aoc2023/src/day6.rs b/aoc2023/src/day6.rs index 267727b..35d9769 100644 --- a/aoc2023/src/day6.rs +++ b/aoc2023/src/day6.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day6)] fn parse(input: &str) -> smallvec::SmallVec<[utils::RaceData; 4]> { use itertools::Itertools; @@ -20,13 +19,16 @@ fn parse(input: &str) -> smallvec::SmallVec<[utils::RaceData; 4]> { } #[aoc(day6, part1)] -fn part1(input: &[utils::RaceData]) -> u64 { +pub fn part1(input: &str) -> u64 { + let input = parse(input); input.iter().map(utils::RaceData::n_record_breaks).product() } #[aoc(day6, part2)] -fn part2(input: &[utils::RaceData]) -> u64 { - utils::RaceData::merge(input).n_record_breaks1() +#[must_use] +pub fn part2(input: &str) -> u64 { + let input = parse(input); + utils::RaceData::merge(&input).n_record_breaks1() } mod utils { @@ -77,12 +79,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 288); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 288); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 71503); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 71503); } } diff --git a/aoc2023/src/day7.rs b/aoc2023/src/day7.rs index f5921e7..5aa8d22 100644 --- a/aoc2023/src/day7.rs +++ b/aoc2023/src/day7.rs @@ -1,23 +1,17 @@ -use aoc_runner_derive::{aoc, aoc_generator}; - -#[aoc_generator(day7, part1)] -fn parse1(input: &str) -> Vec> { - utils::parse(input) -} - -#[aoc_generator(day7, part2)] -fn parse2(input: &str) -> Vec> { - utils::parse(input) -} +use aoc_runner_derive::aoc; #[aoc(day7, part1)] -fn part1(input: &[utils::CardHandWithBid]) -> u64 { - utils::solve(input) +#[must_use] +pub fn part1(input: &str) -> u64 { + let input: Vec> = utils::parse(input); + utils::solve(&input) } #[aoc(day7, part2)] -fn part2(input: &[utils::CardHandWithBid]) -> u64 { - utils::solve(input) +#[must_use] +pub fn part2(input: &str) -> u64 { + let input: Vec> = utils::parse(input); + utils::solve(&input) } mod utils { @@ -300,12 +294,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse1(SAMPLE)), 6440); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 6440); } #[test] - fn part2_example() { - assert_eq!(part2(&parse2(SAMPLE)), 5905); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 5905); } } diff --git a/aoc2023/src/day8.rs b/aoc2023/src/day8.rs index 0c577b5..cc79d4a 100644 --- a/aoc2023/src/day8.rs +++ b/aoc2023/src/day8.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day8)] fn parse(input: &str) -> utils::Network { use itertools::Itertools; @@ -35,7 +34,9 @@ fn parse(input: &str) -> utils::Network { } #[aoc(day8, part1)] -fn part1(input: &utils::Network) -> u64 { +#[must_use] +pub fn part1(input: &str) -> u64 { + let input = parse(input); // Begin at "AAA" let mut current_node = "AAA"; @@ -58,7 +59,8 @@ fn part1(input: &utils::Network) -> u64 { } #[aoc(day8, part2)] -fn part2(input: &utils::Network) -> u64 { +pub fn part2(input: &str) -> u64 { + let input = parse(input); // Find all nodes that end with 'A' let mut nodes: smallvec::SmallVec<[&str; 8]> = input .map @@ -117,7 +119,7 @@ mod tests { use indoc::indoc; #[test] - fn part1_example() { + pub fn part1_example() { const SAMPLE: &str = indoc! {" LLR @@ -125,11 +127,11 @@ mod tests { BBB = (AAA, ZZZ) ZZZ = (ZZZ, ZZZ) "}; - assert_eq!(part1(&parse(SAMPLE)), 6); + assert_eq!(part1(SAMPLE), 6); } #[test] - fn part2_example() { + pub fn part2_example() { const SAMPLE: &str = indoc! {" LR @@ -142,6 +144,6 @@ mod tests { 22Z = (22B, 22B) XXX = (XXX, XXX) "}; - assert_eq!(part2(&parse(SAMPLE)), 6); + assert_eq!(part2(SAMPLE), 6); } } diff --git a/aoc2023/src/day9.rs b/aoc2023/src/day9.rs index 5d9a90b..ae864f3 100644 --- a/aoc2023/src/day9.rs +++ b/aoc2023/src/day9.rs @@ -1,6 +1,5 @@ -use aoc_runner_derive::{aoc, aoc_generator}; +use aoc_runner_derive::aoc; -#[aoc_generator(day9)] fn parse(input: &str) -> Vec> { input .lines() @@ -13,7 +12,9 @@ fn parse(input: &str) -> Vec> { } #[aoc(day9, part1)] -fn part1(input: &[Vec]) -> i32 { +#[must_use] +pub fn part1(input: &str) -> i32 { + let input = parse(input); input .iter() .map(|seq| utils::predict_next_recursively(seq)) @@ -21,12 +22,14 @@ fn part1(input: &[Vec]) -> i32 { } #[aoc(day9, part2)] -fn part2(input: &[Vec]) -> i32 { +#[must_use] +pub fn part2(input: &str) -> i32 { + let input = parse(input); input - .to_owned() + .clone() .iter_mut() .map(|arr| { - arr.reverse(); + (*arr).reverse(); arr }) .map(|seq| utils::predict_next_recursively(seq)) @@ -58,12 +61,12 @@ mod tests { "}; #[test] - fn part1_example() { - assert_eq!(part1(&parse(SAMPLE)), 114); + pub fn part1_example() { + assert_eq!(part1(SAMPLE), 114); } #[test] - fn part2_example() { - assert_eq!(part2(&parse(SAMPLE)), 2); + pub fn part2_example() { + assert_eq!(part2(SAMPLE), 2); } }