From b51e5b8ef272a5eb9fc19dc107480282ab2df285 Mon Sep 17 00:00:00 2001 From: Connor Slade Date: Mon, 16 Dec 2024 16:08:03 -0500 Subject: [PATCH 1/3] [2024] Cleanup day 16 --- aoc_2024/src/day_16.rs | 285 +++++++++++------------------- aoc_lib/src/direction/cardinal.rs | 1 + aoc_lib/src/matrix.rs | 19 +- 3 files changed, 126 insertions(+), 179 deletions(-) diff --git a/aoc_2024/src/day_16.rs b/aoc_2024/src/day_16.rs index c82e689..b650afb 100644 --- a/aoc_2024/src/day_16.rs +++ b/aoc_2024/src/day_16.rs @@ -1,11 +1,33 @@ -use std::collections::{BinaryHeap, HashMap, HashSet}; +use std::{ + cmp::Ordering, + collections::{BinaryHeap, HashSet}, +}; use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; use common::{solution, Answer}; -use nd_vec::{vector, Vec2}; +use nd_vec::Vec2; solution!("Reindeer Maze", 16); +fn part_a(input: &str) -> Answer { + let map = Maze::parse(input); + let (_, shortest) = map.foreword(); + shortest.into() +} + +fn part_b(input: &str) -> Answer { + let map = Maze::parse(input); + let (scores, _) = map.foreword(); + map.reverse(scores).into() +} + +struct Maze { + map: Matrix, + + start: Vec2, + end: Vec2, +} + #[derive(PartialEq, Eq)] enum Tile { Empty, @@ -14,210 +36,117 @@ enum Tile { End, } -fn part_a(input: &str) -> Answer { - let map = Matrix::new_chars(input, |c| match c { - '.' => Tile::Empty, - '#' => Tile::Wall, - 'S' => Tile::Start, - 'E' => Tile::End, - _ => panic!(), - }); - let start = map.find(Tile::Start).unwrap(); - - // find minimum score needed to path from S to E - // - Move foreword (+1) - // - rotate left or right (+1000) - - #[derive(PartialEq, Eq)] - struct Item { - pos: Vec2, - dir: Direction, - score: u32, - } - - impl Ord for Item { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - other.score.cmp(&self.score) - } - } - - impl PartialOrd for Item { - fn partial_cmp(&self, other: &Self) -> Option { - Some(other.score.cmp(&self.score)) - } - } +#[derive(PartialEq, Eq)] +struct Item { + pos: Vec2, + dir: Direction, + score: u32, +} - // todo: try bin heap - let mut queue = BinaryHeap::new(); - let mut seen = HashSet::new(); +impl Maze { + fn parse(input: &str) -> Self { + let map = Matrix::new_chars(input, |c| match c { + '.' => Tile::Empty, + '#' => Tile::Wall, + 'S' => Tile::Start, + 'E' => Tile::End, + _ => panic!(), + }); - queue.push(Item { - pos: start, - dir: Direction::Right, - score: 0, - }); + let start = map.find(Tile::Start).unwrap(); + let end = map.find(Tile::End).unwrap(); - while let Some(Item { pos, dir, score }) = queue.pop() { - if !seen.insert((pos, dir)) { - continue; - } + Self { map, start, end } + } - if map[pos] == Tile::End { - return score.into(); - } + /// Use dijkstra's to find the shortest path, populating a costs grid with + /// the minimum cost needed to reach that tile, which will be used for part B. + fn foreword(&self) -> (Matrix<[u32; 4]>, u32) { + let mut queue = BinaryHeap::new(); + let mut seen = HashSet::new(); + let mut costs = Matrix::new_default(self.map.size, [u32::MAX; 4]); - // Move foreword - let next = dir.wrapping_advance(pos); - if map.contains(next) && map[next] != Tile::Wall { - queue.push(Item { - pos: next, - dir, - score: score + 1, - }); - } + queue.push(Item::new(self.start, Direction::Right, 0)); - queue.push(Item { - pos, - dir: dir.turn_left(), - score: score + 1000, - }); + while let Some(Item { pos, dir, score }) = queue.pop() { + let min = &mut costs[pos]; + min[dir as usize] = min[dir as usize].min(score); - queue.push(Item { - pos, - dir: dir.turn_right(), - score: score + 1000, - }); - } + if !seen.insert((pos, dir)) { + continue; + } - unreachable!() -} + if self.map[pos] == Tile::End { + return (costs, score); + } -fn part_b(input: &str) -> Answer { - let map = Matrix::new_chars(input, |c| match c { - '.' => Tile::Empty, - '#' => Tile::Wall, - 'S' => Tile::Start, - 'E' => Tile::End, - _ => panic!(), - }); - let start = map.find(Tile::Start).unwrap(); - - // find minimum score needed to path from S to E - // - Move foreword (+1) - // - rotate left or right (+1000) - - #[derive(PartialEq, Eq)] - struct Item { - pos: Vec2, - dir: Direction, - score: u32, - - path: Vec>, - } + let next = dir.wrapping_advance(pos); + if self.map.contains(next) && self.map[next] != Tile::Wall { + queue.push(Item::new(next, dir, score + 1)); + } - impl Ord for Item { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - other.score.cmp(&self.score) + for dir in [dir.turn_left(), dir.turn_right()] { + queue.push(Item::new(pos, dir, score + 1000)); + } } - } - impl PartialOrd for Item { - fn partial_cmp(&self, other: &Self) -> Option { - Some(other.score.cmp(&self.score)) - } + unreachable!("No path found") } - // todo: try bin heap - let mut queue = BinaryHeap::new(); - let mut seen = HashMap::new(); - - let mut on_best = HashSet::>::new(); + /// Walks backwards from the end using a BFS to find all the tiles that are + /// on any of the shortest path. + fn reverse(&self, mut scores: Matrix<[u32; 4]>) -> u32 { + let mut seen = HashSet::new(); + let mut seen_queue = vec![]; - queue.push(Item { - pos: start, - dir: Direction::Right, - score: 0, - - path: vec![start], - }); - - let mut best = None; + let end_lowest = scores.get(self.end).unwrap(); + for dir in Direction::ALL { + let min_cost = end_lowest[dir as usize]; + seen_queue.push(Item::new(self.end, dir, min_cost)); + } - while let Some(Item { - pos, - dir, - score, - path, - }) = queue.pop() - { - if let Some(&prev) = seen.get(&(pos, dir)) { - if score > prev { + while let Some(item) = seen_queue.pop() { + seen.insert(item.pos); + if item.pos == self.start { continue; } - } else { - seen.insert((pos, dir), score); - } - if map[pos] == Tile::End { - if let Some(real_best) = best { - dbg!(score, real_best); - if score == real_best { - on_best.extend(path.iter()); + let next = item.dir.opposite().wrapping_advance(item.pos); + for next in [ + Item::new(next, item.dir, item.score - 1), + Item::new(item.pos, item.dir.turn_left(), item.score - 1000), + Item::new(item.pos, item.dir.turn_right(), item.score - 1000), + ] { + if self.map.contains(next.pos) + && self.map[next.pos] != Tile::Wall + && next.score == scores.get(next.pos).unwrap()[next.dir as usize] + { + scores.get_mut(next.pos).unwrap()[next.dir as usize] = u32::MAX; + seen_queue.push(next); } - } else { - best = Some(score); - on_best.extend(path.iter()); } - - continue; - } - - // Move foreword - let next = dir.wrapping_advance(pos); - let mut next_path = path.clone(); - next_path.push(next); - if map.contains(next) && map[next] != Tile::Wall { - queue.push(Item { - pos: next, - dir, - score: score + 1, - path: next_path, - }); } - queue.push(Item { - pos, - dir: dir.turn_left(), - score: score + 1000, - path: path.clone(), - }); + seen.len() as u32 + } +} - queue.push(Item { - pos, - dir: dir.turn_right(), - score: score + 1000, - path, - }); +impl Item { + fn new(pos: Vec2, dir: Direction, score: u32) -> Self { + Self { pos, dir, score } } +} - for y in 0..map.size.y() { - for x in 0..map.size.x() { - let pos = vector!(x, y); - print!( - "{}", - match map[pos] { - Tile::Empty if on_best.contains(&pos) => '@', - Tile::Empty => '.', - Tile::Wall => '#', - Tile::Start => 'S', - Tile::End => 'E', - } - ); - } - println!(); +impl Ord for Item { + fn cmp(&self, other: &Self) -> Ordering { + other.score.cmp(&self.score) } +} - on_best.len().into() +impl PartialOrd for Item { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } #[cfg(test)] diff --git a/aoc_lib/src/direction/cardinal.rs b/aoc_lib/src/direction/cardinal.rs index 05180fb..5cb0ddd 100644 --- a/aoc_lib/src/direction/cardinal.rs +++ b/aoc_lib/src/direction/cardinal.rs @@ -2,6 +2,7 @@ use nd_vec::{vector, Vec2}; use num_traits::{Num, Signed, WrappingSub}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[repr(u8)] pub enum Direction { Up, Down, diff --git a/aoc_lib/src/matrix.rs b/aoc_lib/src/matrix.rs index 3bf80ad..b2ed519 100644 --- a/aoc_lib/src/matrix.rs +++ b/aoc_lib/src/matrix.rs @@ -1,4 +1,8 @@ -use std::{fmt::Debug, hash::Hash, ops::Index}; +use std::{ + fmt::Debug, + hash::Hash, + ops::{Index, IndexMut}, +}; use nd_vec::{vector, Vec2}; use num_traits::{Num, ToPrimitive}; @@ -89,6 +93,12 @@ impl Index<[usize; 2]> for Matrix { } } +impl IndexMut<[usize; 2]> for Matrix { + fn index_mut(&mut self, index: [usize; 2]) -> &mut T { + &mut self.data[index[1] * self.size.x() + index[0]] + } +} + impl Index> for Matrix { type Output = T; @@ -98,6 +108,13 @@ impl Index> for Matrix { } } +impl IndexMut> for Matrix { + fn index_mut(&mut self, index: Vec2) -> &mut T { + let index = index.num_cast::().unwrap(); + &mut self.data[index.y() * self.size.x() + index.x()] + } +} + impl Clone for Matrix { fn clone(&self) -> Self { Self { From f9ebfa3a0e8601c9714025ae888a870b14ce9342 Mon Sep 17 00:00:00 2001 From: Connor Slade Date: Mon, 16 Dec 2024 16:10:20 -0500 Subject: [PATCH 2/3] [LIB] Rename Matrix to Grid --- aoc_2021/src/day_15.rs | 6 +++--- aoc_2023/src/day_14.rs | 6 +++--- aoc_2023/src/day_16.rs | 10 +++++----- aoc_2023/src/day_17.rs | 8 ++++---- aoc_2023/src/day_21.rs | 6 +++--- aoc_2023/src/day_23.rs | 10 +++++----- aoc_2024/src/day_04.rs | 6 +++--- aoc_2024/src/day_06.rs | 6 +++--- aoc_2024/src/day_08.rs | 6 +++--- aoc_2024/src/day_10.rs | 6 +++--- aoc_2024/src/day_12.rs | 6 +++--- aoc_2024/src/day_15.rs | 6 +++--- aoc_2024/src/day_16.rs | 12 ++++++------ aoc_lib/src/matrix.rs | 26 +++++++++++++------------- 14 files changed, 60 insertions(+), 60 deletions(-) diff --git a/aoc_2021/src/day_15.rs b/aoc_2021/src/day_15.rs index dde1dfc..65857bb 100644 --- a/aoc_2021/src/day_15.rs +++ b/aoc_2021/src/day_15.rs @@ -3,7 +3,7 @@ use std::collections::BinaryHeap; use hashbrown::HashMap; use nd_vec::{vector, Vector}; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; solution!("Chiton", 15); @@ -11,12 +11,12 @@ solution!("Chiton", 15); type Point = Vector; fn part_a(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, |chr| chr.to_digit(10).unwrap() as u8); + let matrix = Grid::new(input, |chr| chr.to_digit(10).unwrap() as u8); solve(matrix.size, |pos| matrix.get(pos).copied()).into() } fn part_b(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, |chr| chr.to_digit(10).unwrap() as u8); + let matrix = Grid::new(input, |chr| chr.to_digit(10).unwrap() as u8); solve(matrix.size * 5, |pos| { let (cx, cy) = (pos.x() / matrix.size.x(), pos.y() / matrix.size.y()); if cx > 4 || cy > 4 { diff --git a/aoc_2023/src/day_14.rs b/aoc_2023/src/day_14.rs index 0936139..4c93cc9 100644 --- a/aoc_2023/src/day_14.rs +++ b/aoc_2023/src/day_14.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, convert::identity, hash::Hash}; -use aoc_lib::matrix::Matrix; +use aoc_lib::matrix::Grid; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -35,12 +35,12 @@ fn part_b(input: &str) -> Answer { #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct Dish { - tiles: Matrix, + tiles: Grid, } fn parse(input: &str) -> Dish { Dish { - tiles: Matrix::new_chars(input, identity), + tiles: Grid::new(input, identity), } } diff --git a/aoc_2023/src/day_16.rs b/aoc_2023/src/day_16.rs index cf9ebba..495254b 100644 --- a/aoc_2023/src/day_16.rs +++ b/aoc_2023/src/day_16.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -30,8 +30,8 @@ fn part_b(input: &str) -> Answer { max.into() } -fn parse(input: &str) -> Matrix { - Matrix::new_chars(input, Tile::from_char) +fn parse(input: &str) -> Grid { + Grid::new(input, Tile::from_char) } #[derive(Debug, Clone, Copy, PartialEq)] @@ -43,8 +43,8 @@ enum Tile { SlantRight, // / } -fn lazer(cavern: &Matrix, start: Pos, direction: Direction) -> usize { - fn _lazer(cavern: &Matrix, visited: &mut HashSet, mut pos: Pos, mut dir: Direction) { +fn lazer(cavern: &Grid, start: Pos, direction: Direction) -> usize { + fn _lazer(cavern: &Grid, visited: &mut HashSet, mut pos: Pos, mut dir: Direction) { loop { pos = dir.advance(pos); if !cavern.contains(pos) { diff --git a/aoc_2023/src/day_17.rs b/aoc_2023/src/day_17.rs index 5104354..bae4827 100644 --- a/aoc_2023/src/day_17.rs +++ b/aoc_2023/src/day_17.rs @@ -3,7 +3,7 @@ use std::{ collections::{BinaryHeap, HashMap}, }; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -19,11 +19,11 @@ fn part_b(input: &str) -> Answer { pathfind(parse(input), 4, 10).into() } -fn parse(input: &str) -> Matrix { - Matrix::new_chars(input, |c| c as u8 - b'0') +fn parse(input: &str) -> Grid { + Grid::new(input, |c| c as u8 - b'0') } -fn pathfind(board: Matrix, min_dist: u8, max_dist: u8) -> u32 { +fn pathfind(board: Grid, min_dist: u8, max_dist: u8) -> u32 { let mut queue = BinaryHeap::new(); let mut visited = HashMap::new(); let mut res = u32::MAX; diff --git a/aoc_2023/src/day_21.rs b/aoc_2023/src/day_21.rs index 65bd4a5..970b779 100644 --- a/aoc_2023/src/day_21.rs +++ b/aoc_2023/src/day_21.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -86,8 +86,8 @@ enum Tile { Start, } -fn parse(input: &str) -> Matrix { - Matrix::new_chars(input, |x| match x { +fn parse(input: &str) -> Grid { + Grid::new(input, |x| match x { '#' => Tile::Wall, '.' => Tile::Garden, 'S' => Tile::Start, diff --git a/aoc_2023/src/day_23.rs b/aoc_2023/src/day_23.rs index 3514577..8b5095b 100644 --- a/aoc_2023/src/day_23.rs +++ b/aoc_2023/src/day_23.rs @@ -3,7 +3,7 @@ use std::{ convert::identity, }; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -20,7 +20,7 @@ fn part_b(input: &str) -> Answer { } // Simple DFS to find the longest path for part A -fn solve_a(map: &Matrix, visited: &mut HashSet, pos: Pos, idx: u32) -> u32 { +fn solve_a(map: &Grid, visited: &mut HashSet, pos: Pos, idx: u32) -> u32 { if pos == map.size() - vector!(2, 1) { return idx; } @@ -44,7 +44,7 @@ fn solve_a(map: &Matrix, visited: &mut HashSet, pos: Pos, idx: u32) - } // Convert the map into a graph and collapse it to find the longest path for part B -fn solve_b(map: &Matrix) -> u32 { +fn solve_b(map: &Grid) -> u32 { // == Build graph == let mut graph = HashMap::new(); let mut add_edge = |a: Pos, b: Pos| { @@ -124,8 +124,8 @@ fn solve_b(map: &Matrix) -> u32 { max } -fn parse(input: &str) -> Matrix { - Matrix::new_chars(input, identity) +fn parse(input: &str) -> Grid { + Grid::new(input, identity) } fn dir_matches(dir: Direction, chr: char) -> bool { diff --git a/aoc_2024/src/day_04.rs b/aoc_2024/src/day_04.rs index 298b9c5..1688645 100644 --- a/aoc_2024/src/day_04.rs +++ b/aoc_2024/src/day_04.rs @@ -1,13 +1,13 @@ use std::convert::identity; -use aoc_lib::{direction::ordinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::ordinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::vector; solution!("Ceres Search", 4); fn part_a(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, identity); + let matrix = Grid::new(input, identity); let mut count = 0; for y in 0..matrix.size.y() { @@ -44,7 +44,7 @@ const MAS_DIRECTIONS: [[Direction; 2]; 2] = [ ]; fn part_b(input: &str) -> Answer { - let matrix = Matrix::new_chars(input, identity); + let matrix = Grid::new(input, identity); let mut count = 0; for y in 0..matrix.size.y() { diff --git a/aoc_2024/src/day_06.rs b/aoc_2024/src/day_06.rs index c527ebc..5c3e9b7 100644 --- a/aoc_2024/src/day_06.rs +++ b/aoc_2024/src/day_06.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::Vec2; use rayon::iter::{ParallelBridge, ParallelIterator}; @@ -30,13 +30,13 @@ enum Tile { } struct Map { - map: Matrix, + map: Grid, start: Vec2, } impl Map { fn new(input: &str) -> Self { - let map = Matrix::new_chars(input, |x| match x { + let map = Grid::new(input, |x| match x { '#' => Tile::Obstacle, '^' => Tile::Start, _ => Tile::None, diff --git a/aoc_2024/src/day_08.rs b/aoc_2024/src/day_08.rs index 59359db..60ae0f8 100644 --- a/aoc_2024/src/day_08.rs +++ b/aoc_2024/src/day_08.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use aoc_lib::matrix::Matrix; +use aoc_lib::matrix::Grid; use common::{solution, Answer}; use nd_vec::Vec2; @@ -52,7 +52,7 @@ fn part_b(input: &str) -> Answer { } struct AntennaMap { - world: Matrix, + world: Grid, freqs: HashMap>>, } @@ -63,7 +63,7 @@ enum Tile { impl AntennaMap { fn parse(input: &str) -> Self { - let world = Matrix::new_chars(input, |x| match x { + let world = Grid::new(input, |x| match x { 'a'..='z' | 'A'..='Z' | '0'..='9' => Tile::Emitter(x), _ => Tile::Empty, }); diff --git a/aoc_2024/src/day_10.rs b/aoc_2024/src/day_10.rs index 823c19b..42e28fd 100644 --- a/aoc_2024/src/day_10.rs +++ b/aoc_2024/src/day_10.rs @@ -1,6 +1,6 @@ use std::collections::{HashSet, VecDeque}; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::Vec2; @@ -22,12 +22,12 @@ fn solve(input: &str, part_b: bool) -> usize { } struct Map { - board: Matrix, + board: Grid, } impl Map { fn parse(input: &str) -> Self { - let board = Matrix::new_chars(input, |x| x.to_digit(10).unwrap()); + let board = Grid::new(input, |x| x.to_digit(10).unwrap()); Self { board } } diff --git a/aoc_2024/src/day_12.rs b/aoc_2024/src/day_12.rs index f3d5eb6..0d7ce6c 100644 --- a/aoc_2024/src/day_12.rs +++ b/aoc_2024/src/day_12.rs @@ -1,6 +1,6 @@ use std::{collections::HashSet, convert::identity}; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use itertools::Itertools; use nd_vec::{vector, Vec2}; @@ -51,14 +51,14 @@ fn part_b(input: &str) -> Answer { } struct Garden { - matrix: Matrix, + matrix: Grid, seen: HashSet>, } impl Garden { fn parse(input: &str) -> Self { - let matrix = Matrix::new_chars(input, identity); + let matrix = Grid::new(input, identity); Self { matrix, seen: HashSet::new(), diff --git a/aoc_2024/src/day_15.rs b/aoc_2024/src/day_15.rs index 655ee63..d5fb683 100644 --- a/aoc_2024/src/day_15.rs +++ b/aoc_2024/src/day_15.rs @@ -1,4 +1,4 @@ -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::{vector, Vec2}; @@ -20,7 +20,7 @@ struct Problem { pos: Vec2, idx: usize, - board: Matrix, + board: Grid, instructions: Vec, } @@ -36,7 +36,7 @@ enum Tile { impl Problem { fn parse(input: &str, part_b: bool) -> Self { let (board, instructions) = input.split_once("\n\n").unwrap(); - let mut board = Matrix::new_chars(board, |chr| match chr { + let mut board = Grid::new(board, |chr| match chr { '@' => Tile::Robot, '#' => Tile::Wall, 'O' => Tile::Box, diff --git a/aoc_2024/src/day_16.rs b/aoc_2024/src/day_16.rs index b650afb..660395f 100644 --- a/aoc_2024/src/day_16.rs +++ b/aoc_2024/src/day_16.rs @@ -3,7 +3,7 @@ use std::{ collections::{BinaryHeap, HashSet}, }; -use aoc_lib::{direction::cardinal::Direction, matrix::Matrix}; +use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; use nd_vec::Vec2; @@ -22,7 +22,7 @@ fn part_b(input: &str) -> Answer { } struct Maze { - map: Matrix, + map: Grid, start: Vec2, end: Vec2, @@ -45,7 +45,7 @@ struct Item { impl Maze { fn parse(input: &str) -> Self { - let map = Matrix::new_chars(input, |c| match c { + let map = Grid::new(input, |c| match c { '.' => Tile::Empty, '#' => Tile::Wall, 'S' => Tile::Start, @@ -61,10 +61,10 @@ impl Maze { /// Use dijkstra's to find the shortest path, populating a costs grid with /// the minimum cost needed to reach that tile, which will be used for part B. - fn foreword(&self) -> (Matrix<[u32; 4]>, u32) { + fn foreword(&self) -> (Grid<[u32; 4]>, u32) { let mut queue = BinaryHeap::new(); let mut seen = HashSet::new(); - let mut costs = Matrix::new_default(self.map.size, [u32::MAX; 4]); + let mut costs = Grid::parse(self.map.size, [u32::MAX; 4]); queue.push(Item::new(self.start, Direction::Right, 0)); @@ -95,7 +95,7 @@ impl Maze { /// Walks backwards from the end using a BFS to find all the tiles that are /// on any of the shortest path. - fn reverse(&self, mut scores: Matrix<[u32; 4]>) -> u32 { + fn reverse(&self, mut scores: Grid<[u32; 4]>) -> u32 { let mut seen = HashSet::new(); let mut seen_queue = vec![]; diff --git a/aoc_lib/src/matrix.rs b/aoc_lib/src/matrix.rs index b2ed519..342618a 100644 --- a/aoc_lib/src/matrix.rs +++ b/aoc_lib/src/matrix.rs @@ -7,14 +7,14 @@ use std::{ use nd_vec::{vector, Vec2}; use num_traits::{Num, ToPrimitive}; -pub struct Matrix { +pub struct Grid { pub data: Vec, pub size: Vec2, } #[allow(dead_code)] -impl Matrix { - pub fn new_default(size: Vec2, default: T) -> Self +impl Grid { + pub fn parse(size: Vec2, default: T) -> Self where T: Clone, { @@ -24,7 +24,7 @@ impl Matrix { } } - pub fn new_chars(input: &str, parse: fn(char) -> T) -> Self { + pub fn new(input: &str, parse: fn(char) -> T) -> Self { let mut data = Vec::with_capacity(input.len()); let mut size = vector!(0, 0); @@ -85,7 +85,7 @@ impl Matrix { } } -impl Index<[usize; 2]> for Matrix { +impl Index<[usize; 2]> for Grid { type Output = T; fn index(&self, index: [usize; 2]) -> &Self::Output { @@ -93,13 +93,13 @@ impl Index<[usize; 2]> for Matrix { } } -impl IndexMut<[usize; 2]> for Matrix { +impl IndexMut<[usize; 2]> for Grid { fn index_mut(&mut self, index: [usize; 2]) -> &mut T { &mut self.data[index[1] * self.size.x() + index[0]] } } -impl Index> for Matrix { +impl Index> for Grid { type Output = T; fn index(&self, index: Vec2) -> &Self::Output { @@ -108,14 +108,14 @@ impl Index> for Matrix { } } -impl IndexMut> for Matrix { +impl IndexMut> for Grid { fn index_mut(&mut self, index: Vec2) -> &mut T { let index = index.num_cast::().unwrap(); &mut self.data[index.y() * self.size.x() + index.x()] } } -impl Clone for Matrix { +impl Clone for Grid { fn clone(&self) -> Self { Self { data: self.data.clone(), @@ -124,22 +124,22 @@ impl Clone for Matrix { } } -impl PartialEq for Matrix { +impl PartialEq for Grid { fn eq(&self, other: &Self) -> bool { self.data == other.data && self.size == other.size } } -impl Eq for Matrix {} +impl Eq for Grid {} -impl Hash for Matrix { +impl Hash for Grid { fn hash(&self, state: &mut H) { self.data.hash(state); self.size.hash(state); } } -impl Debug for Matrix { +impl Debug for Grid { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for y in 0..self.size.y() { for x in 0..self.size.x() { From 9f369131112a81f34fbb484cae1af9d569014390 Mon Sep 17 00:00:00 2001 From: Connor Slade Date: Mon, 16 Dec 2024 16:11:14 -0500 Subject: [PATCH 3/3] [2024] Fix clippy lints --- aoc_2024/src/day_11.rs | 2 +- aoc_2024/src/day_13.rs | 2 +- aoc_2024/src/day_15.rs | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/aoc_2024/src/day_11.rs b/aoc_2024/src/day_11.rs index 3df0e4d..953c971 100644 --- a/aoc_2024/src/day_11.rs +++ b/aoc_2024/src/day_11.rs @@ -35,7 +35,7 @@ fn solve(nums: Vec, iters: usize) -> u64 { counts = next; } - counts.values().sum::().into() + counts.values().sum::() } fn parse(input: &str) -> Vec { diff --git a/aoc_2024/src/day_13.rs b/aoc_2024/src/day_13.rs index 854c59a..8a15c0d 100644 --- a/aoc_2024/src/day_13.rs +++ b/aoc_2024/src/day_13.rs @@ -77,7 +77,7 @@ impl Problem { } fn solve(&self) -> u64 { - self.cases.iter().map(|x| x.cheapest()).sum::().into() + self.cases.iter().map(|x| x.cheapest()).sum::() } fn part_b(mut self) -> Self { diff --git a/aoc_2024/src/day_15.rs b/aoc_2024/src/day_15.rs index d5fb683..051198f 100644 --- a/aoc_2024/src/day_15.rs +++ b/aoc_2024/src/day_15.rs @@ -96,12 +96,10 @@ impl Problem { self.idx += 1; let new = dir.advance(self.pos); - if { - if part_b { - self.push_b(new, dir) - } else { - self.push(new, dir) - } + if if part_b { + self.push_b(new, dir) + } else { + self.push(new, dir) } { self.pos = new; }