diff --git a/aoc_2024/src/day_18.rs b/aoc_2024/src/day_18.rs index b52ccbd..6656598 100644 --- a/aoc_2024/src/day_18.rs +++ b/aoc_2024/src/day_18.rs @@ -1,8 +1,4 @@ -use std::{ - collections::{HashMap, HashSet, VecDeque}, - fmt::{Debug, Write}, - usize, -}; +use std::collections::{HashSet, VecDeque}; use aoc_lib::{direction::cardinal::Direction, matrix::Grid}; use common::{solution, Answer}; @@ -12,39 +8,40 @@ solution!("RAM Run", 18); fn part_a(input: &str) -> Answer { let mut map = Map::parse(input, vector!(71, 71)); - map.fill_all(); + map.fill_to(1023); map.shortest_path().into() } fn part_b(input: &str) -> Answer { let mut map = Map::parse(input, vector!(71, 71)); - loop { - let next = map.fill_next(); - if map.shortest_path() == usize::MAX { - return format!("{},{}", next.x(), next.y()).into(); - } - } - unreachable!() -} + let (mut start, mut end) = (0, map.falling.len() - 1); -#[derive(Clone, PartialEq, Eq)] -enum Tile { - Filled, - Empty, -} + while start <= end { + let mid = (start + end) / 2; + let next = map.fill_to(mid); + + let works = map.shortest_path() != usize::MAX; + + if !works && { + map.fill_to(mid - 1); + map.shortest_path() != usize::MAX + } { + return format!("{},{}", next.x(), next.y()).into(); + } -impl Debug for Tile { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Tile::Filled => f.write_char('#'), - Tile::Empty => f.write_char('.'), + if works { + start = mid + 1; + } else { + end = mid - 1; } } + + panic!("No solution found") } struct Map { - board: Grid, + board: Grid, falling: Vec>, } @@ -58,23 +55,18 @@ impl Map { }) .collect::>(); - let board = Grid::parse(size, Tile::Empty); + let board = Grid::parse(size, false); Self { falling, board } } - fn fill_next(&mut self) -> Vec2 { - let pos = self.falling.remove(0); - self.board.set(pos, Tile::Filled); - pos - } - - fn fill_all(&mut self) { - for ins in &self.falling[0..1024] { - self.board.set(*ins, Tile::Filled); + fn fill_to(&mut self, end: usize) -> Vec2 { + self.board.fill(false); + for ins in &self.falling[0..=end] { + self.board.set(*ins, true); } - println!("{:?}", self.board); + self.falling[end] } fn shortest_path(&self) -> usize { @@ -93,7 +85,7 @@ impl Map { for dir in Direction::ALL { let next = dir.wrapping_advance(pos); - if self.board.get(next) == Some(&Tile::Empty) { + if self.board.get(next) == Some(&false) { queue.push_back((next, depth + 1)); } } @@ -106,6 +98,9 @@ impl Map { #[cfg(test)] mod test { use indoc::indoc; + use nd_vec::vector; + + use super::Map; const CASE: &str = indoc! {" 5,4 @@ -137,11 +132,8 @@ mod test { #[test] fn part_a() { - assert_eq!(super::part_a(CASE), 22.into()); - } - - #[test] - fn part_b() { - assert_eq!(super::part_b(CASE), ().into()); + let mut map = Map::parse(CASE, vector!(7, 7)); + map.fill_to(11); + assert_eq!(map.shortest_path(), 22); } } diff --git a/aoc_lib/src/matrix.rs b/aoc_lib/src/matrix.rs index 342618a..f4c1716 100644 --- a/aoc_lib/src/matrix.rs +++ b/aoc_lib/src/matrix.rs @@ -12,7 +12,6 @@ pub struct Grid { pub size: Vec2, } -#[allow(dead_code)] impl Grid { pub fn parse(size: Vec2, default: T) -> Self where @@ -85,6 +84,12 @@ impl Grid { } } +impl Grid { + pub fn fill(&mut self, value: T) { + self.data.fill(value); + } +} + impl Index<[usize; 2]> for Grid { type Output = T;