1
0
Fork 0

day(18): use tricks from day(10) to solve part 2

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2023-12-18 19:21:41 +01:00
parent 69287d8a30
commit 9a5d814792
Signed by: mfocko
GPG key ID: 7C47D46246790496

View file

@ -1,6 +1,7 @@
use std::{collections::VecDeque, str::FromStr}; use std::{
collections::BTreeMap,
use itertools::iproduct; str::FromStr,
};
use aoc_2023::*; use aoc_2023::*;
@ -48,73 +49,47 @@ impl Step {
} }
} }
fn flood_fill(m: &mut [Vec<char>], start: Vector2D<isize>, original: char, fill: char) -> usize { fn dir_to_u8(u: (isize, isize)) -> u8 {
let mut filled_in = 0; match u {
(0, 1) => 1,
let mut q: VecDeque<Vector2D<isize>> = VecDeque::from([start]); (0, -1) => 2,
m[start] = fill; (1, 0) => 4,
filled_in += 1; (-1, 0) => 8,
_ => unreachable!(),
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;
}
} }
}
filled_in fn opposite(u: (isize, isize)) -> (isize, isize) {
(-u.0, -u.1)
} }
fn solve(plan: &[Step]) -> usize { 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 hole: BTreeMap<Vector2D<isize>, u8> = BTreeMap::new();
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 position = Vector2D::new(0, 0);
for s in plan.iter() { for s in plan.iter() {
let direction = s.direction(); let direction = s.direction();
for _ in 0..s.count { for _ in 0..s.count {
map[position] = '#'; *hole.entry(position).or_insert(0) |= dir_to_u8(s._direction);
position = position + direction; position = position + direction;
*hole.entry(position).or_insert(0) |= dir_to_u8(opposite(s._direction));
} }
} }
flood_fill(&mut map, Vector2D::new(0, 0), '.', '+'); let mut counter = 0;
let mut in_between = 0;
while let Some((y, x)) = let mut x_prev = 0;
iproduct!(0..height as usize, 0..width as usize).find(|&(y, x)| map[y][x] == '.') for (v, directions) in hole.iter() {
{ if in_between != 0 && x_prev < v.x() {
flood_fill(&mut map, Vector2D::new(x as isize, y as isize), '.', '#'); // debug!("{} {}", v.x(), x_prev);
counter += (v.x() - x_prev) as usize - 1;
}
in_between ^= directions & 3;
x_prev = v.x();
} }
// debug!( counter + hole.len()
// "Map:\n{}",
// map.iter().map(|r| r.iter().collect::<String>()).join("\n")
// );
map.iter()
.map(|r| r.iter().filter(|&&c| c == '#').count())
.sum()
} }
struct Day18 { struct Day18 {
@ -150,7 +125,7 @@ impl Solution<Output1, Output2> for Day18 {
Step { Step {
_direction, _direction,
count: number >> 8, count: number >> 4,
color: String::new(), color: String::new(),
} }
}) })