From 3c9bfef10a88e53f95247631281e215d251881ae Mon Sep 17 00:00:00 2001 From: Bauke Date: Sun, 14 Jan 2024 22:04:10 +0100 Subject: [PATCH] Add missing documentation lints. --- Cargo.toml | 4 ++++ source/main.rs | 3 ++- source/solution.rs | 22 ++++++++++++++++++++++ source/templates/mod.rs | 6 ++++++ source/utilities.rs | 8 ++++++++ source/year_2020/day_01/mod.rs | 7 +++++++ source/year_2020/day_02/mod.rs | 11 +++++++++++ source/year_2020/day_03/mod.rs | 7 +++++++ source/year_2020/day_04/mod.rs | 15 +++++++++++++++ source/year_2020/day_05/mod.rs | 11 +++++++++++ source/year_2020/day_06/mod.rs | 5 +++++ source/year_2020/day_07/mod.rs | 9 +++++++++ source/year_2020/day_08/mod.rs | 17 +++++++++++++++++ source/year_2020/day_09/mod.rs | 7 +++++++ source/year_2020/day_10/mod.rs | 6 ++++++ source/year_2020/day_11/grid.rs | 21 ++++++++++++++++++++- source/year_2020/day_11/mod.rs | 6 ++++++ source/year_2020/day_12/extra.rs | 13 +++++++++++++ source/year_2020/day_12/mod.rs | 6 ++++++ source/year_2020/day_13/mod.rs | 5 +++++ source/year_2020/day_14/mod.rs | 6 ++++++ source/year_2020/day_14/operation.rs | 5 +++++ source/year_2020/day_15/mod.rs | 6 ++++++ source/year_2020/day_16/mod.rs | 6 ++++++ source/year_2020/mod.rs | 3 +++ source/year_2021/day_01/mod.rs | 6 ++++++ source/year_2021/day_02/mod.rs | 17 +++++++++++++++++ source/year_2021/day_03/mod.rs | 6 ++++++ source/year_2021/day_04/bingo.rs | 5 +++++ source/year_2021/day_04/board.rs | 6 ++++++ source/year_2021/day_04/mod.rs | 5 +++++ source/year_2021/day_05/mod.rs | 12 ++++++++++++ source/year_2021/day_06/mod.rs | 9 +++++++++ source/year_2021/day_07/mod.rs | 6 ++++++ source/year_2021/day_08/display.rs | 6 ++++++ source/year_2021/day_08/mod.rs | 5 +++++ source/year_2021/day_09/mod.rs | 11 +++++++++++ source/year_2021/day_10/mod.rs | 5 +++++ source/year_2021/day_13/canvas.rs | 11 +++++++++++ source/year_2021/day_13/mod.rs | 6 ++++++ source/year_2021/day_14/mod.rs | 11 +++++++++++ source/year_2021/day_15/mod.rs | 13 +++++++++++++ source/year_2021/mod.rs | 3 +++ 43 files changed, 356 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f054802..8acf60c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,5 +27,9 @@ rand = "0.8.5" regex = "1.10.2" ureq = { version = "2.8.0", features = ["cookie", "cookie_store"] } +[lints.clippy] +missing_docs_in_private_items = "warn" + [lints.rust] +missing_docs = "warn" unsafe_code = "forbid" diff --git a/source/main.rs b/source/main.rs index 2118f6e..84be233 100644 --- a/source/main.rs +++ b/source/main.rs @@ -15,6 +15,7 @@ pub mod utilities; pub mod year_2020; pub mod year_2021; +/// CLI arguments. #[derive(Debug, Parser)] #[clap(about, author, version)] pub struct Args { @@ -22,7 +23,7 @@ pub struct Args { pub filter: Option, } -pub fn main() -> Result<()> { +fn main() -> Result<()> { color_eyre::install()?; let args = Args::parse(); diff --git a/source/solution.rs b/source/solution.rs index fbd1bd4..cf55d12 100644 --- a/source/solution.rs +++ b/source/solution.rs @@ -1,53 +1,72 @@ +//! Functionality for [`Day`]s and [`Solution`]s. + use {color_eyre::Result, derivative::Derivative}; +/// The information for an advent day of a given year. #[derive(Debug)] pub struct Day { + /// The advent day. pub day: i32, + /// The year for the advent. pub year: i32, } impl Day { + /// Create a new [`Day`] from a given day and year. pub fn new(day: i32, year: i32) -> Self { Self { day, year } } + /// Return the filter string as `YEAR::DAY` for this day. pub fn filter_string(&self) -> String { format!("{}::{:02}", self.year, self.day) } + /// Return the link for this day on the Advent of Code website. pub fn day_link(&self) -> String { format!("{}/day/{}", self.year_link(), self.day) } + /// Return the link for this year on the Advent of Code website. pub fn year_link(&self) -> String { format!("https://adventofcode.com/{}", self.year) } } +/// Function type alias for the expected input and outputs of a day. pub type DayFunction = fn(input: &str) -> Result; +/// The solution to one of the advent calendar days. #[derive(Derivative)] #[derivative(Debug)] pub struct Solution { + /// Which day the solution applies to. pub day: Day, + /// The calculated result for part one. pub part_1: String, + /// The calculated result for part two. pub part_2: String, + /// The expected result for part one (for validation). pub part_1_expected: String, + /// The expected result for part two (for validation). pub part_2_expected: String, + /// The function for part one. #[derivative(Debug = "ignore")] pub part_1_fn: DayFunction, + /// The function for part two. #[derivative(Debug = "ignore")] pub part_2_fn: DayFunction, } impl Solution { + /// Create a new [`Solution`] with a given [`Day`] and two [`DayFunction`]s. pub fn new(day: Day, part_1_fn: DayFunction, part_2_fn: DayFunction) -> Self { Self { day, @@ -60,6 +79,7 @@ impl Solution { } } + /// Helper function to add the expected results for both parts. pub fn with_expected( self, part_1_expected: A, @@ -72,6 +92,8 @@ impl Solution { } } + /// Run the [`DayFunction`]s for this [`Solution`] and put the results in + /// their respective fields. pub fn solve(self, data: &str) -> Result { let (part_1, part_2) = ((self.part_1_fn)(data)?, (self.part_2_fn)(data)?); Ok(Self { diff --git a/source/templates/mod.rs b/source/templates/mod.rs index b3cc8c5..1c26004 100644 --- a/source/templates/mod.rs +++ b/source/templates/mod.rs @@ -1,14 +1,20 @@ +//! The templating code for [`askama`]. + use askama::Template; use crate::solution::Solution; +/// The HTML template for all solutions. #[derive(Template)] #[template(path = "solutions.html")] pub struct SolutionsTemplate { + /// All solutions grouped by year. pub years: Vec>, } +/// Custom [`askama`] filters. pub mod filters { + /// See [`crate::utilities::random_emoji`]. pub fn random_emoji(s: &str) -> askama::Result { Ok(format!("{s} {}", crate::utilities::random_emoji())) } diff --git a/source/utilities.rs b/source/utilities.rs index f0d780e..50c2c8b 100644 --- a/source/utilities.rs +++ b/source/utilities.rs @@ -1,3 +1,5 @@ +//! Miscellaneous utility functions. + use std::{ fs::{create_dir_all, read_to_string, write}, path::PathBuf, @@ -7,10 +9,12 @@ use {color_eyre::Result, dialoguer::Password, rand::seq::IteratorRandom}; use crate::{solution::Solution, year_2020, year_2021}; +/// Shorthand to get the solutions for all years. pub fn get_solutions() -> Vec> { vec![year_2020::get_solutions(), year_2021::get_solutions()] } +/// Return a random emoji from the [`emojis::Group::AnimalsAndNature`] set. pub fn random_emoji() -> String { emojis::iter() .filter(|emoji| emoji.group() == emojis::Group::AnimalsAndNature) @@ -19,6 +23,8 @@ pub fn random_emoji() -> String { .to_string() } +/// Get the Advent of Code session cookie from an existing file or start an +/// interactive prompt to ask the user for it. pub fn session_cookie() -> Result { let session_cookie_path = PathBuf::from("aoc/session.txt"); @@ -33,6 +39,8 @@ pub fn session_cookie() -> Result { } } +/// Write the given contents to a path, ensuring the parent directory for the +/// location exists. pub fn write_file(path: PathBuf, contents: String) -> Result { create_dir_all(path.parent().unwrap())?; write(path, &contents)?; diff --git a/source/year_2020/day_01/mod.rs b/source/year_2020/day_01/mod.rs index 6830670..ac2d7d8 100644 --- a/source/year_2020/day_01/mod.rs +++ b/source/year_2020/day_01/mod.rs @@ -1,12 +1,17 @@ +//! Day 01 of 2020. + use crate::prelude::*; +/// Get the solution for day 01 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(1, 2020), part_1, part_2) .with_expected(605364, 128397680) } +/// The target sum that two entries need to add up to. const TARGET: i32 = 2020; +/// Parse the input lines into integers. fn parse_lines(input: &str) -> Vec { input .lines() @@ -14,6 +19,7 @@ fn parse_lines(input: &str) -> Vec { .collect() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( parse_lines(input) @@ -26,6 +32,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok( parse_lines(input) diff --git a/source/year_2020/day_02/mod.rs b/source/year_2020/day_02/mod.rs index 74092ae..c545410 100644 --- a/source/year_2020/day_02/mod.rs +++ b/source/year_2020/day_02/mod.rs @@ -1,17 +1,26 @@ +//! Day 02 of 2020. + use crate::prelude::*; +/// Get the solution for day 02 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(2, 2020), part_1, part_2).with_expected(638, 699) } +/// The data for each line of the puzzle input. #[derive(Debug)] struct Item { + /// The minimum amount of times the letter has to be in the password. min: usize, + /// The maximum amount of times the letter has to be in the password. max: usize, + /// The letter that must be in the password. letter: String, + /// The password to check. password: String, } +/// Parse all the [`Item`]s inside the puzzle input. fn parse_items(input: &str) -> Vec { let mut items = vec![]; @@ -32,6 +41,7 @@ fn parse_items(input: &str) -> Vec { items } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( parse_items(input) @@ -43,6 +53,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok( parse_items(input) diff --git a/source/year_2020/day_03/mod.rs b/source/year_2020/day_03/mod.rs index 8b2f4b8..591a95e 100644 --- a/source/year_2020/day_03/mod.rs +++ b/source/year_2020/day_03/mod.rs @@ -1,10 +1,15 @@ +//! Day 03 of 2020. + use crate::prelude::*; +/// Get the solution for day 03 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(3, 2020), part_1, part_2) .with_expected(198, 5140884672_i64) } +/// Generic solver that takes in a horizontal and vertical movement for the +/// slope. fn solve(data: &str, (horizontal, vertical): (usize, usize)) -> usize { let line_length = data.find('\n').unwrap(); let mut result = 0; @@ -28,10 +33,12 @@ fn solve(data: &str, (horizontal, vertical): (usize, usize)) -> usize { result } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok(solve(input, (3, 1)).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok( [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)] diff --git a/source/year_2020/day_04/mod.rs b/source/year_2020/day_04/mod.rs index 94a706d..53cb634 100644 --- a/source/year_2020/day_04/mod.rs +++ b/source/year_2020/day_04/mod.rs @@ -1,21 +1,34 @@ +//! Day 04 of 2020. + use crate::prelude::*; +/// Get the solution for day 04 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(4, 2020), part_1, part_2).with_expected(237, 172) } +/// The passport puzzle input. #[derive(Debug, Clone)] struct Passport { + /// Birth year. byr: Option, + /// Issue year. iyr: Option, + /// Expiration year. eyr: Option, + /// Height. hgt: Option, + /// Hair color. hcl: Option, + /// Eye color. ecl: Option, + /// Passport ID. pid: Option, + /// Country ID. cid: Option, } +/// Parse the puzzle input into a list of passports. fn parse_passports(input: &str) -> Vec { let mut passports = vec![]; let blank = Passport { @@ -59,6 +72,7 @@ fn parse_passports(input: &str) -> Vec { passports } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( parse_passports(input) @@ -77,6 +91,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let hcl_regex = Regex::new("^#[a-fA-F0-9]{6}$").unwrap(); let pid_regex = Regex::new("^[0-9]{9}$").unwrap(); diff --git a/source/year_2020/day_05/mod.rs b/source/year_2020/day_05/mod.rs index deb3dfc..61d55ce 100644 --- a/source/year_2020/day_05/mod.rs +++ b/source/year_2020/day_05/mod.rs @@ -1,12 +1,20 @@ +//! Day 05 of 2020. + use crate::prelude::*; +/// Get the solution for day 05 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(5, 2020), part_1, part_2).with_expected(850, 599) } +/// The maximum range of rows. const MAX_ROW_RANGE: i32 = 128; + +/// The maximum range of columns. const MAX_COLUMN_RANGE: i32 = 8; +/// Calculate the row and column from the input according to the puzzle's +/// instructions. fn calculate_row_and_column(input: &str) -> (i32, i32) { let mut row_range = 0..MAX_ROW_RANGE; let mut column_range = 0..MAX_COLUMN_RANGE; @@ -40,10 +48,12 @@ fn calculate_row_and_column(input: &str) -> (i32, i32) { (row_range.start, column_range.start) } +/// Calculate the sead ID by multiplying the row by 8 and adding the column. fn calculate_seat_id((row, column): (i32, i32)) -> i32 { (row * 8) + column } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( input @@ -56,6 +66,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let seat_ids = input .lines() diff --git a/source/year_2020/day_06/mod.rs b/source/year_2020/day_06/mod.rs index 9c672f1..ecd5d18 100644 --- a/source/year_2020/day_06/mod.rs +++ b/source/year_2020/day_06/mod.rs @@ -1,9 +1,13 @@ +//! Day 06 of 2020. + use crate::prelude::*; +/// Get the solution for day 06 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(6, 2020), part_1, part_2).with_expected(6437, 3229) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( input @@ -20,6 +24,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok( input diff --git a/source/year_2020/day_07/mod.rs b/source/year_2020/day_07/mod.rs index 0751960..0ec3c84 100644 --- a/source/year_2020/day_07/mod.rs +++ b/source/year_2020/day_07/mod.rs @@ -1,11 +1,16 @@ +//! Day 07 of 2020. + use crate::prelude::*; +/// Get the solution for day 07 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(7, 2020), part_1, part_2).with_expected(169, 82372) } +/// The target bag to look for. const TARGET: &str = "shiny gold"; +/// Parse the bags from the puzzle input. fn parse_bags(input: &str) -> Vec<(&str, Vec<(usize, &str)>)> { let mut bags = vec![]; @@ -29,6 +34,7 @@ fn parse_bags(input: &str) -> Vec<(&str, Vec<(usize, &str)>)> { bags } +/// Find out which bags can hold the [`TARGET`] bag. fn can_hold_target_bag<'a>( target: &'a str, bags: &[(&'a str, Vec<(usize, &'a str)>)], @@ -44,6 +50,7 @@ fn can_hold_target_bag<'a>( can_hold } +/// Find out how many bags are required to be inside the [`TARGET`] bag. fn target_bag_holds_amount<'a>( target: &'a str, bags: &[(&'a str, Vec<(usize, &'a str)>)], @@ -64,6 +71,7 @@ fn target_bag_holds_amount<'a>( count } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( can_hold_target_bag(TARGET, &parse_bags(input)) @@ -74,6 +82,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok(target_bag_holds_amount("shiny gold", &parse_bags(input)).to_string()) } diff --git a/source/year_2020/day_08/mod.rs b/source/year_2020/day_08/mod.rs index 3d5b5bd..d99fbbb 100644 --- a/source/year_2020/day_08/mod.rs +++ b/source/year_2020/day_08/mod.rs @@ -1,13 +1,20 @@ +//! Day 08 of 2020. + use crate::prelude::*; +/// Get the solution for day 08 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(8, 2020), part_1, part_2).with_expected(1814, 1056) } +/// The possible operations an instruction can perform. #[derive(Debug, Eq, PartialEq, Hash, Clone)] enum Operation { + /// Increase or decrease the accumulator. Acc, + /// Jump to a new instruction. Jmp, + /// Do nothing, no operation. Nop, } @@ -22,12 +29,17 @@ impl From<&str> for Operation { } } +/// Type alias for the arguments of operations. type Argument = i32; +/// A single instruction. #[derive(Debug, Eq, PartialEq, Hash, Clone)] struct Instruction { + /// The line the instruction was parsed from, used for debugging. line: usize, + /// The operation to perform. op: Operation, + /// The argument for the operation. arg: Argument, } @@ -42,6 +54,8 @@ impl From<(usize, &str)> for Instruction { } } +/// Execute the list of instructions and return the accumulator and whether or +/// not an infinite loop was encountered. fn execute(instructions: &[Instruction]) -> (i32, bool) { let mut seen_instructions = HashSet::new(); @@ -69,14 +83,17 @@ fn execute(instructions: &[Instruction]) -> (i32, bool) { (accumulator, encountered_infinite_loop) } +/// Parse the list of instructions from the puzzle input. fn parse_instructions(input: &str) -> Vec { input.lines().enumerate().map(Into::into).collect() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok(execute(&parse_instructions(input)).0.to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let instructions = parse_instructions(input); let mut part_2_result = None; diff --git a/source/year_2020/day_09/mod.rs b/source/year_2020/day_09/mod.rs index af6d398..4b61e6c 100644 --- a/source/year_2020/day_09/mod.rs +++ b/source/year_2020/day_09/mod.rs @@ -1,12 +1,17 @@ +//! Day 09 of 2020. + use crate::prelude::*; +/// Get the solution for day 09 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(9, 2020), part_1, part_2) .with_expected(22477624, 2980044) } +/// The amount of numbers to consider as the preamble. const PREAMBLE_LENGTH: usize = 25; +/// Parse the puzzle input into a list of numbers. fn parse_numbers(input: &str) -> Vec { input .lines() @@ -14,6 +19,7 @@ fn parse_numbers(input: &str) -> Vec { .collect() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let numbers = parse_numbers(input); let mut result_one = 0; @@ -47,6 +53,7 @@ fn part_1(input: &str) -> Result { Ok(result_one.to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let numbers = parse_numbers(input); let result_one = part_1(input)?; diff --git a/source/year_2020/day_10/mod.rs b/source/year_2020/day_10/mod.rs index 52a0b7d..55a7e27 100644 --- a/source/year_2020/day_10/mod.rs +++ b/source/year_2020/day_10/mod.rs @@ -1,10 +1,14 @@ +//! Day 10 of 2020. + use crate::prelude::*; +/// Get the solution for day 10 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(10, 2020), part_1, part_2) .with_expected(2368, 1727094849536_i64) } +/// Parse the puzzle input and return the intervals and streaks of the adapters. fn parse_numbers(input: &str) -> (HashMap, HashMap) { let mut numbers = input .lines() @@ -35,11 +39,13 @@ fn parse_numbers(input: &str) -> (HashMap, HashMap) { (intervals, streaks) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let (intervals, _) = parse_numbers(input); Ok((intervals.get(&1).unwrap() * intervals.get(&3).unwrap()).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let (_, streaks) = parse_numbers(input); Ok( diff --git a/source/year_2020/day_11/grid.rs b/source/year_2020/day_11/grid.rs index bb5dc90..79547bc 100644 --- a/source/year_2020/day_11/grid.rs +++ b/source/year_2020/day_11/grid.rs @@ -1,14 +1,24 @@ +//! [`Grid`], [`Cell`] and [`Ruleset`] code. + +/// The different types of cell available in the [`Grid`]. #[derive(Debug, Eq, PartialEq, Clone)] pub enum Cell { + /// The cell is an edge of the grid. Edge, + /// The cell is a floor tile. Floor, + /// The cell is an empty seat. Empty, + /// The cell is an occupied seat. Occupied, } +/// The different rulesets for part one and two. #[derive(Debug, Eq, PartialEq)] pub enum Ruleset { + /// The ruleset for part one. PartOne, + /// The ruleset for part two. PartTwo, } @@ -24,16 +34,23 @@ impl From for Cell { } } +/// The grid of seats. #[derive(Debug)] pub struct Grid { + /// The length of lines from the puzzle input. pub line_length: isize, + /// The amount of [`Cell`]s that are occupied. pub occupied_cell_count: usize, + /// How tolerant people are for seats to become empty. pub occupied_cell_tolerance: usize, + /// The list of [`Cell`]s. pub cells: Vec, + /// Which [`Ruleset`] is being used. pub ruleset: Ruleset, } impl Grid { + /// Create a new grid based on the puzzle input and which [`Ruleset`] to use. pub fn new(input: &str, ruleset: Ruleset) -> Self { let line_length = input.find('\n').unwrap() + 2; @@ -62,6 +79,7 @@ impl Grid { } } + /// Simulate a single step and return the new list of [`Cell`]s. pub fn simulate_step(&self) -> Vec { let mut cells = self.cells.clone(); @@ -137,11 +155,12 @@ impl Grid { cells } + /// Count the amount of [`Cell`]s matching a given target. pub fn count_cells(&self, target: Cell) -> usize { self.cells.iter().filter(|cell| cell == &&target).count() } - // Useful for debugging. + /// Draw the grid, used for debugging. pub fn _draw(&self) -> String { let mut result = String::new(); for (index, cell) in self.cells.iter().enumerate() { diff --git a/source/year_2020/day_11/mod.rs b/source/year_2020/day_11/mod.rs index f47f1f5..36e02f8 100644 --- a/source/year_2020/day_11/mod.rs +++ b/source/year_2020/day_11/mod.rs @@ -1,13 +1,17 @@ +//! Day 11 of 2020. + use crate::prelude::*; mod grid; use grid::*; +/// Get the solution for day 11 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(11, 2020), part_1, part_2).with_expected(2243, 2027) } +/// Calculate the result based on the ruleset. fn calculate(input: &str, ruleset: Ruleset) -> usize { let mut grid = Grid::new(input, ruleset); @@ -28,10 +32,12 @@ fn calculate(input: &str, ruleset: Ruleset) -> usize { previous_occupied_cell_count.unwrap() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok(calculate(input, Ruleset::PartOne).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok(calculate(input, Ruleset::PartTwo).to_string()) } diff --git a/source/year_2020/day_12/extra.rs b/source/year_2020/day_12/extra.rs index 19bbfa5..c991869 100644 --- a/source/year_2020/day_12/extra.rs +++ b/source/year_2020/day_12/extra.rs @@ -1,11 +1,21 @@ +//! [`Action`] and [`Instruction`] code. + +/// The list of actions the ship can take. #[derive(Debug, Eq, PartialEq)] pub enum Action { + /// Move North by a given value. North, + /// Move East by a given value. East, + /// Move South by a given value. South, + /// Move West by a given value. West, + /// Turn left by a given number of degrees. Left, + /// Turn right by a given number of degrees. Right, + /// Move forward by a given value in the direction the ship is facing. Forward, } @@ -24,9 +34,12 @@ impl From for Action { } } +/// The combination of an [`Action`] and the value for it. #[derive(Debug)] pub struct Instruction { + /// Which action to take. pub action: Action, + /// The amount to use for that action. pub value: i32, } diff --git a/source/year_2020/day_12/mod.rs b/source/year_2020/day_12/mod.rs index 8c9e063..eb56431 100644 --- a/source/year_2020/day_12/mod.rs +++ b/source/year_2020/day_12/mod.rs @@ -1,17 +1,22 @@ +//! Day 12 of 2020. + use crate::prelude::*; mod extra; use extra::*; +/// Get the solution for day 12 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(12, 2020), part_1, part_2).with_expected(1496, 63843) } +/// Parse the list of [`Instruction`]s based on the puzzle input. fn parse_instructions(input: &str) -> Vec { input.lines().map(Into::into).collect() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let instructions = parse_instructions(input); let mut horizontal = 0; @@ -48,6 +53,7 @@ fn part_1(input: &str) -> Result { Ok((horizontal.abs() + vertical.abs()).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let instructions = parse_instructions(input); diff --git a/source/year_2020/day_13/mod.rs b/source/year_2020/day_13/mod.rs index 93d8925..07acf44 100644 --- a/source/year_2020/day_13/mod.rs +++ b/source/year_2020/day_13/mod.rs @@ -1,10 +1,14 @@ +//! Day 13 of 2020. + use crate::prelude::*; +/// Get the solution for day 13 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(13, 2020), part_1, part_2) .with_expected(1895, 840493039281088_i64) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let mut lines = input.lines(); @@ -33,6 +37,7 @@ fn part_1(input: &str) -> Result { Ok((earliest_bus * difference).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { // Skip the first line, as it isn't used for the second part of the puzzle. let input = input.lines().nth(1).unwrap(); diff --git a/source/year_2020/day_14/mod.rs b/source/year_2020/day_14/mod.rs index 5f52c10..f0f747e 100644 --- a/source/year_2020/day_14/mod.rs +++ b/source/year_2020/day_14/mod.rs @@ -1,14 +1,18 @@ +//! Day 14 of 2020. + use crate::prelude::*; mod operation; use operation::*; +/// Get the solution for day 14 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(14, 2020), part_1, part_2) .with_expected(9967721333886_i64, 4355897790573_i64) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let operations = input.lines().map(Into::into).collect::>(); @@ -35,6 +39,7 @@ fn part_1(input: &str) -> Result { Ok(memory.values().sum::().to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let operations = input.lines().map(Into::into).collect::>(); @@ -95,6 +100,7 @@ fn part_2(input: &str) -> Result { Ok(memory.values().sum::().to_string()) } +/// Loop over the input mask and replace any floating bits. fn combine(input: String) -> Vec { let mut result = vec![]; diff --git a/source/year_2020/day_14/operation.rs b/source/year_2020/day_14/operation.rs index 5719b37..3b1d978 100644 --- a/source/year_2020/day_14/operation.rs +++ b/source/year_2020/day_14/operation.rs @@ -1,6 +1,11 @@ +//! [`Operation`] parsing code. + +/// The list of operations to perform. #[derive(Debug)] pub enum Operation { + /// Set the mask using a given string. SetMask(String), + /// Set the memory of an address to a given value. SetMemory(i64, i64), } diff --git a/source/year_2020/day_15/mod.rs b/source/year_2020/day_15/mod.rs index 53645c8..54ebf1a 100644 --- a/source/year_2020/day_15/mod.rs +++ b/source/year_2020/day_15/mod.rs @@ -1,9 +1,13 @@ +//! Day 15 of 2020. + use crate::prelude::*; +/// Get the solution for day 15 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(15, 2020), part_1, part_2).with_expected(441, 10613991) } +/// Solve the puzzle for a given target. fn solve(input: &str, target: usize) -> isize { let mut numbers = HashMap::new(); let mut previous_number = (0, (0, 0)); @@ -33,10 +37,12 @@ fn solve(input: &str, target: usize) -> isize { *numbers.iter().max_by(|a, b| a.1 .1.cmp(&b.1 .1)).unwrap().0 } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok(solve(input, 2020).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok(solve(input, 30000000).to_string()) } diff --git a/source/year_2020/day_16/mod.rs b/source/year_2020/day_16/mod.rs index e21ace8..1a526e9 100644 --- a/source/year_2020/day_16/mod.rs +++ b/source/year_2020/day_16/mod.rs @@ -1,10 +1,14 @@ +//! Day 16 of 2020. + use crate::prelude::*; +/// Get the solution for day 16 of 2020. pub fn solution() -> Solution { Solution::new(Day::new(16, 2020), part_1, part_2) .with_expected(26980, 3021381607403_i64) } +/// Solve the puzzle. fn solve(input: &str, return_part_1: bool) -> Result { let mut parts = input.trim().split("\n\n"); let mut ranges = vec![]; @@ -133,10 +137,12 @@ fn solve(input: &str, return_part_1: bool) -> Result { Ok(result_two) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { solve(input, true) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { solve(input, false) } diff --git a/source/year_2020/mod.rs b/source/year_2020/mod.rs index ce9cb33..5f11b2a 100644 --- a/source/year_2020/mod.rs +++ b/source/year_2020/mod.rs @@ -1,3 +1,5 @@ +//! Solutions for Advent of Code 2020. + use crate::solution::Solution; mod day_01; @@ -17,6 +19,7 @@ mod day_14; mod day_15; mod day_16; +/// Get all the solutions of 2020 as a [`Vec`]. pub fn get_solutions() -> Vec { vec![ day_01::solution(), diff --git a/source/year_2021/day_01/mod.rs b/source/year_2021/day_01/mod.rs index 49feabb..0abadad 100644 --- a/source/year_2021/day_01/mod.rs +++ b/source/year_2021/day_01/mod.rs @@ -1,9 +1,13 @@ +//! Day 01 of 2021. + use crate::prelude::*; +/// Get the solution for day 01 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(1, 2021), part_1, part_2).with_expected(1451, 1395) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( parse_measurements(input)? @@ -15,6 +19,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { Ok( parse_measurements(input)? @@ -26,6 +31,7 @@ fn part_2(input: &str) -> Result { ) } +/// Parse the measurements from the puzzle input. fn parse_measurements(input: &str) -> Result> { input .lines() diff --git a/source/year_2021/day_02/mod.rs b/source/year_2021/day_02/mod.rs index 440a6d2..59b9d8d 100644 --- a/source/year_2021/day_02/mod.rs +++ b/source/year_2021/day_02/mod.rs @@ -1,14 +1,21 @@ +//! Day 02 of 2021. + use crate::prelude::*; +/// Get the solution for day 02 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(2, 2021), part_1, part_2) .with_expected(1727835, 1544000595) } +/// The possible commands to execute. #[derive(Debug)] enum Command { + /// Move forward a given amount. Forward(i32), + /// Move down a given amount. Down(i32), + /// Move up a given amount. Up(i32), } @@ -34,14 +41,19 @@ impl FromStr for Command { } } +/// The submarine data. #[derive(Debug, Default)] struct Submarine { + /// The direction the submarine is aiming at. aim: i32, + /// The depth of the submarine is at. depth: i32, + /// The horizontal position of the submarine. horizontal_position: i32, } impl Submarine { + /// Execute the [`Command`] according to the logic for part one. fn execute_command_1(&mut self, command: Command) { match command { Command::Forward(amount) => self.horizontal_position += amount, @@ -50,6 +62,7 @@ impl Submarine { } } + /// Execute the [`Command`] according to the logic for part two. fn execute_command_2(&mut self, command: Command) { match command { Command::Forward(amount) => { @@ -61,15 +74,18 @@ impl Submarine { } } + /// Calculate the final result. fn final_result(&self) -> i32 { self.horizontal_position * self.depth } } +/// Parse the list of [`Command`]s from the puzzle input. fn parse_commands(input: &str) -> Result> { input.lines().map(Command::from_str).collect::>() } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let mut submarine = Submarine::default(); @@ -80,6 +96,7 @@ fn part_1(input: &str) -> Result { Ok(submarine.final_result().to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let mut submarine = Submarine::default(); diff --git a/source/year_2021/day_03/mod.rs b/source/year_2021/day_03/mod.rs index d55d7aa..a88045c 100644 --- a/source/year_2021/day_03/mod.rs +++ b/source/year_2021/day_03/mod.rs @@ -1,10 +1,14 @@ +//! Day 03 of 2021. + use crate::prelude::*; +/// Get the solution for day 03 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(3, 2021), part_1, part_2) .with_expected(1092896, 4672151) } +/// Count the bits for each line of the puzzle input. fn count_bits(input: &str) -> Result> { let mut bits = HashMap::::new(); @@ -28,6 +32,7 @@ fn count_bits(input: &str) -> Result> { ) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let bits = count_bits(input)?; @@ -51,6 +56,7 @@ fn part_1(input: &str) -> Result { Ok((gamma_rate * epsilon_rate).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let mut most_common_lines = input.lines().collect::>(); let mut least_common_lines = input.lines().collect::>(); diff --git a/source/year_2021/day_04/bingo.rs b/source/year_2021/day_04/bingo.rs index 6238b30..2e4de85 100644 --- a/source/year_2021/day_04/bingo.rs +++ b/source/year_2021/day_04/bingo.rs @@ -1,12 +1,17 @@ +//! [`Bingo`] code and implementation. + use std::str::FromStr; use color_eyre::eyre::{eyre, Error}; use super::board::Board; +/// The game of bingo to play with its boards and numbers. #[derive(Debug)] pub struct Bingo { + /// The list of [`Board`]s to play bingo with. pub boards: Vec, + /// The list of numbers to play. pub numbers: Vec, } diff --git a/source/year_2021/day_04/board.rs b/source/year_2021/day_04/board.rs index 4a507e1..cebf6c4 100644 --- a/source/year_2021/day_04/board.rs +++ b/source/year_2021/day_04/board.rs @@ -1,3 +1,5 @@ +//! [`Board`] code and implementation. + use std::str::FromStr; use color_eyre::eyre::Error; @@ -18,9 +20,13 @@ const WIN_MATRIX: &[&[usize]] = &[ &[4, 9, 14, 19, 24], ]; +/// A single bingo board. #[derive(Debug, Clone)] pub struct Board { + /// Whether this board has at least one line filled. pub has_won: bool, + /// The state of the board, with indexes determining the position and whether + /// that position has been filled. pub state: Vec<(i32, bool)>, } diff --git a/source/year_2021/day_04/mod.rs b/source/year_2021/day_04/mod.rs index 97ffebe..61dad9c 100644 --- a/source/year_2021/day_04/mod.rs +++ b/source/year_2021/day_04/mod.rs @@ -1,3 +1,5 @@ +//! Day 04 of 2021. + mod bingo; mod board; @@ -5,16 +7,19 @@ use bingo::Bingo; use crate::prelude::*; +/// Get the solution for day 04 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(4, 2021), part_1, part_2).with_expected(8580, 9576) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let (winning_board, latest_number) = Bingo::from_str(input)?.play_until_first_win(); Ok((winning_board.sum_unmarked() * latest_number).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let (winning_board, latest_number) = Bingo::from_str(input)?.play_until_last_win(); diff --git a/source/year_2021/day_05/mod.rs b/source/year_2021/day_05/mod.rs index 2582f20..ac2fba1 100644 --- a/source/year_2021/day_05/mod.rs +++ b/source/year_2021/day_05/mod.rs @@ -1,16 +1,23 @@ +//! Day 05 of 2021. + use crate::prelude::*; +/// Get the solution for day 05 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(5, 2021), part_1, part_2).with_expected(6687, 19851) } +/// A vector of two sets of coordinates. #[derive(Debug)] struct Vector { + /// The starting coordinate. a: (isize, isize), + /// The ending coordinate. b: (isize, isize), } impl Vector { + /// Calculate the covered diagonal coordinates of the [`Vector`]. fn diagonal_coordinates(&self) -> Vec<(isize, isize)> { let x_coordinates = { let x_amount = (self.a.0 - self.b.0).abs(); @@ -33,6 +40,7 @@ impl Vector { x_coordinates.into_iter().zip(y_coordinates).collect() } + /// Calculate the covered horizontal coordinates of the [`Vector`]. fn horizontal_coordinates(&self) -> Vec<(isize, isize)> { let y = self.a.1; @@ -45,6 +53,7 @@ impl Vector { (x1..=x2).map(|x| (x, y)).collect() } + /// Calculate the covered vertical coordinates of the [`Vector`]. fn vertical_coordinates(&self) -> Vec<(isize, isize)> { let x = self.a.0; @@ -79,6 +88,7 @@ impl FromStr for Vector { } } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let vectors = input .lines() @@ -110,6 +120,7 @@ fn part_1(input: &str) -> Result { Ok(count_result(travelled_coordinates).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let vectors = input .lines() @@ -135,6 +146,7 @@ fn part_2(input: &str) -> Result { Ok(count_result(travelled_coordinates).to_string()) } +/// Count the results of the coordinates that overlap at least two lines. fn count_result(coordinates: HashMap<(isize, isize), isize>) -> usize { coordinates .into_iter() diff --git a/source/year_2021/day_06/mod.rs b/source/year_2021/day_06/mod.rs index c4a22df..8c9bd50 100644 --- a/source/year_2021/day_06/mod.rs +++ b/source/year_2021/day_06/mod.rs @@ -1,12 +1,17 @@ +//! Day 06 of 2021. + use crate::prelude::*; +/// Shorthand for a [`HashMap`] using [`isize`]s. type FishMap = HashMap; +/// Get the solution for day 06 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(6, 2021), part_1, part_2) .with_expected(343441, 1569108373832_i64) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let mut fishes = parse_fishes(input)?; @@ -17,6 +22,7 @@ fn part_1(input: &str) -> Result { Ok(count_fishes(fishes).to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let mut fishes = parse_fishes(input)?; @@ -27,6 +33,7 @@ fn part_2(input: &str) -> Result { Ok(count_fishes(fishes).to_string()) } +/// Parse the [`FishMap`]s from the puzzle input. fn parse_fishes(input: &str) -> Result { let mut fishes = FishMap::new(); let individual_fishes = input @@ -42,10 +49,12 @@ fn parse_fishes(input: &str) -> Result { Ok(fishes) } +/// Get the sum of the [`FishMap`] values. fn count_fishes(fishes: FishMap) -> isize { fishes.values().sum() } +/// Simulate the fishes according to the puzzle's instructions. fn simulate_fishes(fishes: FishMap) -> FishMap { let mut new_fishes = HashMap::new(); diff --git a/source/year_2021/day_07/mod.rs b/source/year_2021/day_07/mod.rs index b817ead..8829fc3 100644 --- a/source/year_2021/day_07/mod.rs +++ b/source/year_2021/day_07/mod.rs @@ -1,10 +1,14 @@ +//! Day 07 of 2021. + use crate::prelude::*; +/// Get the solution for day 07 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(7, 2021), part_1, part_2) .with_expected(328318, 89791146) } +/// Parse the list and highest number of crabs from the puzzle input. fn parse_crabs(input: &str) -> Result<(Vec, isize)> { let crabs = input .split(',') @@ -19,6 +23,7 @@ fn parse_crabs(input: &str) -> Result<(Vec, isize)> { Ok((crabs, highest_crab)) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let (crabs, highest_crab) = parse_crabs(input)?; (0..=highest_crab) @@ -33,6 +38,7 @@ fn part_1(input: &str) -> Result { .ok_or_else(|| eyre!("Unable to find lowest fuel")) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let (crabs, highest_crab) = parse_crabs(input)?; (0..=highest_crab) diff --git a/source/year_2021/day_08/display.rs b/source/year_2021/day_08/display.rs index 4ff0c23..ea23532 100644 --- a/source/year_2021/day_08/display.rs +++ b/source/year_2021/day_08/display.rs @@ -1,17 +1,23 @@ +//! [`Display`] implementation. + use std::collections::{HashMap, HashSet}; use color_eyre::Result; +/// Type alias for [`HashSet`] with [`char`]s. pub type CharSet = HashSet; +/// The display with a given size and set of characters. #[derive(Debug)] pub struct Display(pub isize, pub CharSet); impl Display { + /// Parse a [`Display`] from a string. pub fn parse(s: &str) -> Self { Self(s.len() as isize, CharSet::from_iter(s.chars())) } + /// Calculate the remaining displays based on the existing other ones. pub fn figure_out_from_others( others: Vec, ) -> Result> { diff --git a/source/year_2021/day_08/mod.rs b/source/year_2021/day_08/mod.rs index 30fc7c6..608006b 100644 --- a/source/year_2021/day_08/mod.rs +++ b/source/year_2021/day_08/mod.rs @@ -1,13 +1,17 @@ +//! Day 08 of 2021. + mod display; use display::{CharSet, Display}; use crate::prelude::*; +/// Get the solution for day 08 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(8, 2021), part_1, part_2).with_expected(521, 1016804) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { Ok( input @@ -27,6 +31,7 @@ fn part_1(input: &str) -> Result { ) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let mut sum = 0; diff --git a/source/year_2021/day_09/mod.rs b/source/year_2021/day_09/mod.rs index 9356975..7590971 100644 --- a/source/year_2021/day_09/mod.rs +++ b/source/year_2021/day_09/mod.rs @@ -1,13 +1,19 @@ +//! Day 09 of 2021. + use crate::prelude::*; +/// Get the solution for day 09 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(9, 2021), part_1, part_2).with_expected(600, 987840) } +/// Type alias for an [`isize`] tuple. type Coordinate = (isize, isize); +/// Type alias for a [`HashMap`] with [`Coordinate`]s pointing to a value. type HeightMap = HashMap; +/// Constants for coordinate offsets to adjacent positions. const ADJACENT_OFFSETS: &[Coordinate] = &[ (-1, 0), // Left (1, 0), // Right @@ -15,6 +21,7 @@ const ADJACENT_OFFSETS: &[Coordinate] = &[ (0, 1), // Down ]; +/// Parse the [`HeightMap`] from the puzzle input. fn parse_heightmap(input: &str) -> Result { let mut height_map = HeightMap::new(); @@ -32,6 +39,7 @@ fn parse_heightmap(input: &str) -> Result { Ok(height_map) } +/// Parse the map bounds uzing the puzzle input. fn parse_map_bounds(input: &str) -> Result { Ok(( input @@ -44,6 +52,7 @@ fn parse_map_bounds(input: &str) -> Result { )) } +/// Discover all the basins according to the puzzle instructions. fn discover_basins( coordinate: Coordinate, discovered_coordinates: &mut Vec, @@ -74,6 +83,7 @@ fn discover_basins( coordinates } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let height_map = parse_heightmap(input)?; let map_bounds = parse_map_bounds(input)?; @@ -103,6 +113,7 @@ fn part_1(input: &str) -> Result { Ok(risk_level.to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let height_map = parse_heightmap(input)?; let map_bounds = parse_map_bounds(input)?; diff --git a/source/year_2021/day_10/mod.rs b/source/year_2021/day_10/mod.rs index 32ea991..3d24cea 100644 --- a/source/year_2021/day_10/mod.rs +++ b/source/year_2021/day_10/mod.rs @@ -1,10 +1,14 @@ +//! Day 10 of 2021. + use crate::prelude::*; +/// Get the solution for day 10 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(10, 2021), part_1, part_2) .with_expected(387363, 4330777059_i64) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let mut syntax_error_score = 0; @@ -40,6 +44,7 @@ fn part_1(input: &str) -> Result { Ok(syntax_error_score.to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let mut scores = vec![]; diff --git a/source/year_2021/day_13/canvas.rs b/source/year_2021/day_13/canvas.rs index 831e319..e7f9300 100644 --- a/source/year_2021/day_13/canvas.rs +++ b/source/year_2021/day_13/canvas.rs @@ -1,22 +1,33 @@ +//! [`Point`], [`Fold`] and [`Canvas`] implementation. + use std::{collections::HashSet, fmt::Display}; +/// A point coordinate. #[derive(Debug, Hash, PartialEq, Eq)] pub struct Point(pub isize, pub isize); +/// The types of fold that can be made. #[derive(Debug)] pub enum Fold { + /// A horizontal fold going left. Horizontal(isize), + /// A vertical fold going up. Vertical(isize), } +/// The canvas of the paper. #[derive(Debug)] pub struct Canvas { + /// The width of the canvas. pub width: isize, + /// The height of the canvas. pub height: isize, + /// The points on the canvas. pub points: HashSet, } impl Canvas { + /// Perform a fold on the canvas and return the resulting version of it. pub fn fold(self, fold: &Fold) -> Self { let (width, height) = match fold { Fold::Horizontal(amount) => (self.width, *amount), diff --git a/source/year_2021/day_13/mod.rs b/source/year_2021/day_13/mod.rs index 2289e19..77d9add 100644 --- a/source/year_2021/day_13/mod.rs +++ b/source/year_2021/day_13/mod.rs @@ -1,9 +1,12 @@ +//! Day 13 of 2021. + mod canvas; use canvas::{Canvas, Fold, Point}; use crate::prelude::*; +/// Get the solution for day 13 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(13, 2021), part_1, part_2).with_expected( "712", @@ -17,6 +20,7 @@ pub fn solution() -> Solution { ) } +/// Parse the canvas and list of folds to perform from the puzzle input. fn parse(input: &str) -> Result<(Canvas, Vec)> { let mut canvas = Canvas { width: 0, @@ -74,12 +78,14 @@ fn parse(input: &str) -> Result<(Canvas, Vec)> { Ok((canvas, folds)) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let (mut canvas, folds) = parse(input)?; canvas = canvas.fold(&folds[0]); Ok(canvas.points.len().to_string()) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let (mut canvas, folds) = parse(input)?; diff --git a/source/year_2021/day_14/mod.rs b/source/year_2021/day_14/mod.rs index c564952..38d6710 100644 --- a/source/year_2021/day_14/mod.rs +++ b/source/year_2021/day_14/mod.rs @@ -1,13 +1,19 @@ +//! Day 14 of 2021. + use crate::prelude::*; +/// Type alias for a map of pairs. type PairMap = HashMap<(char, char), char>; +/// Type alias for a map of pair counts. type PairCounts = HashMap<(char, char), isize>; +/// Get the solution for day 14 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(14, 2021), part_1, part_2) .with_expected(3411, 7477815755570_i64) } +/// Parse the puzzle input into the template and map of pairs. fn parse(input: &str) -> Result<(String, PairMap)> { let mut lines = input.lines(); let template = lines @@ -30,6 +36,7 @@ fn parse(input: &str) -> Result<(String, PairMap)> { Ok((template, pairs)) } +/// Apply the counts to the pairs and return the new counts to add. fn apply(counts: &PairCounts, pairs: &PairMap) -> PairCounts { let mut to_add = PairCounts::new(); @@ -43,6 +50,7 @@ fn apply(counts: &PairCounts, pairs: &PairMap) -> PairCounts { to_add } +/// Count the totals of the pair counts. fn count_totals(counts: &PairCounts) -> HashMap { let mut totals = HashMap::new(); @@ -55,6 +63,7 @@ fn count_totals(counts: &PairCounts) -> HashMap { totals } +/// Solve the puzzle for a given amount of steps. fn run(input: &str, steps: isize) -> Result { let (template, pairs) = parse(input)?; @@ -80,10 +89,12 @@ fn run(input: &str, steps: isize) -> Result { Ok((max - min).to_string()) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { run(input, 10) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { run(input, 40) } diff --git a/source/year_2021/day_15/mod.rs b/source/year_2021/day_15/mod.rs index b506787..426332c 100644 --- a/source/year_2021/day_15/mod.rs +++ b/source/year_2021/day_15/mod.rs @@ -1,19 +1,26 @@ +//! Day 15 of 2021. + use crate::prelude::*; +/// Get the solution for day 15 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(15, 2021), part_1, part_2).with_expected(386, 2806) } +/// Type alias for a map of coordinates and risk levels. type Grid = HashMap; +/// A coordinate in the grid. #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] struct Coordinate(isize, isize); impl Coordinate { + /// Get the distance between two [`Coordinate`]s. fn distance(&self, target: &Coordinate) -> usize { self.0.abs_diff(target.0) + self.1.abs_diff(target.1) } + /// Calculate the successors of the grid based on this [`Coordinate`]. fn successors(&self, grid: &Grid) -> Vec<(Coordinate, isize)> { let &Coordinate(x, y) = self; let mut successors = vec![]; @@ -33,6 +40,7 @@ impl Coordinate { } } +/// Parse the [`Grid`] and end [`Coordinate`] from the puzzle input. fn parse(input: &str) -> Result<(Grid, Coordinate)> { let mut grid = Grid::new(); let mut end = Coordinate(0, 0); @@ -53,6 +61,8 @@ fn parse(input: &str) -> Result<(Grid, Coordinate)> { Ok((grid, end)) } +/// Enlarge the grid by five times its size, accounting for the additional rules +/// specified in the puzzle. fn enlarge_grid(grid: Grid, end: Coordinate) -> (Grid, Coordinate) { let Coordinate(width, height) = end; let mut larger_grid = grid.clone(); @@ -74,6 +84,7 @@ fn enlarge_grid(grid: Grid, end: Coordinate) -> (Grid, Coordinate) { (larger_grid, Coordinate(width * 5, height * 5)) } +/// Solve the grid using [`astar`]. fn run(grid: Grid, end: Coordinate) -> Result { Ok( astar( @@ -88,11 +99,13 @@ fn run(grid: Grid, end: Coordinate) -> Result { ) } +/// The logic to solve part one. fn part_1(input: &str) -> Result { let (grid, end) = parse(input)?; run(grid, end) } +/// The logic to solve part two. fn part_2(input: &str) -> Result { let (grid, end) = parse(input)?; let (grid, end) = enlarge_grid(grid, end); diff --git a/source/year_2021/mod.rs b/source/year_2021/mod.rs index ffc27af..e433f57 100644 --- a/source/year_2021/mod.rs +++ b/source/year_2021/mod.rs @@ -1,3 +1,5 @@ +//! Solutions for Advent of Code 2021. + use crate::solution::Solution; mod day_01; @@ -14,6 +16,7 @@ mod day_13; mod day_14; mod day_15; +/// Get all the solutions of 2021 as a [`Vec`]. pub fn get_solutions() -> Vec { vec![ day_01::solution(),