diff --git a/src/bin/day18.rs b/src/bin/day18.rs index e98ed73..28f49a3 100644 --- a/src/bin/day18.rs +++ b/src/bin/day18.rs @@ -1,6 +1,7 @@ -use std::{collections::VecDeque, str::FromStr}; - -use itertools::iproduct; +use std::{ + collections::BTreeMap, + str::FromStr, +}; use aoc_2023::*; @@ -48,73 +49,47 @@ impl Step { } } -fn flood_fill(m: &mut [Vec], start: Vector2D, original: char, fill: char) -> usize { - let mut filled_in = 0; - - let mut q: VecDeque> = VecDeque::from([start]); - m[start] = fill; - filled_in += 1; - - while let Some(p) = q.pop_front() { - for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)] { - let neighbour = p + Vector2D::new(dx, dy); - if !in_range(m, &neighbour) || m[neighbour] != original { - continue; - } - - q.push_back(neighbour); - m[neighbour] = fill; - filled_in += 1; - } +fn dir_to_u8(u: (isize, isize)) -> u8 { + match u { + (0, 1) => 1, + (0, -1) => 2, + (1, 0) => 4, + (-1, 0) => 8, + _ => unreachable!(), } +} - filled_in +fn opposite(u: (isize, isize)) -> (isize, isize) { + (-u.0, -u.1) } fn solve(plan: &[Step]) -> usize { - let (min_x, max_x, min_y, max_y) = plan.iter().fold((0, 0, 0, 0), |dimensions, s| { - let (mut lx, mut ux, mut ly, mut uy) = dimensions; - - match s._direction { - (0, 1) => uy += s.count, - (0, -1) => ly += s.count, - (1, 0) => ux += s.count, - (-1, 0) => lx += s.count, - _ => unreachable!(), - } - - (lx, ux, ly, uy) - }); - let (width, height) = (min_x + max_x + 1, min_y + max_y + 1); - debug!("Dimensions: {}×{}", width, height); - - let mut map = vec![vec!['.'; width as usize]; height as usize]; - let mut position = Vector2D::new(min_x, min_y); + let mut hole: BTreeMap, u8> = BTreeMap::new(); + let mut position = Vector2D::new(0, 0); for s in plan.iter() { let direction = s.direction(); + for _ in 0..s.count { - map[position] = '#'; + *hole.entry(position).or_insert(0) |= dir_to_u8(s._direction); position = position + direction; + *hole.entry(position).or_insert(0) |= dir_to_u8(opposite(s._direction)); } } - flood_fill(&mut map, Vector2D::new(0, 0), '.', '+'); - - while let Some((y, x)) = - iproduct!(0..height as usize, 0..width as usize).find(|&(y, x)| map[y][x] == '.') - { - flood_fill(&mut map, Vector2D::new(x as isize, y as isize), '.', '#'); + let mut counter = 0; + let mut in_between = 0; + let mut x_prev = 0; + for (v, directions) in hole.iter() { + if in_between != 0 && x_prev < v.x() { + // debug!("{} {}", v.x(), x_prev); + counter += (v.x() - x_prev) as usize - 1; + } + in_between ^= directions & 3; + x_prev = v.x(); } - // debug!( - // "Map:\n{}", - // map.iter().map(|r| r.iter().collect::()).join("\n") - // ); - - map.iter() - .map(|r| r.iter().filter(|&&c| c == '#').count()) - .sum() + counter + hole.len() } struct Day18 { @@ -150,7 +125,7 @@ impl Solution for Day18 { Step { _direction, - count: number >> 8, + count: number >> 4, color: String::new(), } })