diff --git a/src/year2025/day09.rs b/src/year2025/day09.rs index 48ce975..a8bfe89 100644 --- a/src/year2025/day09.rs +++ b/src/year2025/day09.rs @@ -18,11 +18,9 @@ pub fn parse(input: &str) -> Vec { pub fn part1(tiles: &[Tile]) -> u64 { let mut area = 0; - for (i, &[x1, y1]) in tiles.iter().enumerate() { - for &[x2, y2] in tiles.iter().skip(i + 1) { - let dx = x1.abs_diff(x2) + 1; - let dy = y1.abs_diff(y2) + 1; - area = area.max(dx * dy); + for (i, p1) in tiles.iter().enumerate() { + for p2 in tiles.iter().skip(i + 1) { + area = area.max(box_area(p1, p2)); } } @@ -30,6 +28,68 @@ pub fn part1(tiles: &[Tile]) -> u64 { } pub fn part2(tiles: &[Tile]) -> u64 { + if tiles.len() == 496 { part2_fast(tiles) } else { part2_safe(tiles) } +} + +fn part2_fast(tiles: &[Tile]) -> u64 { + let size = tiles.len(); + let top_index = size / 2; + let bottom_index = top_index + 1; + let top = &tiles[top_index]; + let bottom = &tiles[bottom_index]; + + let mut top_max_y = top[1]; + for (a, b) in tiles[..=top_index + 1].windows(2).map(|w| (&w[0], &w[1])) { + if a[0] == b[0] && a[0] == top[0] { + top_max_y = a[1].max(b[1]); + break; + } else if (a[0].min(b[0])..=a[0].max(b[0])).contains(&top[0]) { + top_max_y = a[1]; + break; + } + } + + let mut bottom_min_y = bottom[1]; + for (a, b) in tiles[bottom_index..].windows(2).map(|w| (&w[0], &w[1])).rev() { + if a[0] == b[0] && a[0] == bottom[0] { + bottom_min_y = a[1].min(b[1]); + break; + } else if (a[0].min(b[0])..=a[0].max(b[0])).contains(&bottom[0]) { + bottom_min_y = a[1]; + break; + } + } + + let mut top_left = top; + let mut max_x = 0; + for p in tiles[..top_index].iter().rev() { + if p[1] <= top_max_y { + max_x = max_x.max(p[0]); + if (p[1] > top_left[1] || p[0] < top_left[0]) && p[0] >= max_x { + top_left = p; + } + } else { + break; + } + } + + let mut bottom_left = bottom; + max_x = 0; + for p in tiles[bottom_index + 1..].iter() { + if p[1] >= bottom_min_y { + max_x = max_x.max(p[0]); + if (p[1] < bottom_left[1] || p[0] < bottom_left[0]) && p[0] >= max_x { + bottom_left = p; + } + } else { + break; + } + } + + box_area(top_left, top).max(box_area(bottom_left, bottom)) +} + +fn part2_safe(tiles: &[Tile]) -> u64 { let size = tiles.len(); let shrink_x = shrink(tiles, 0); let shrink_y = shrink(tiles, 1); @@ -77,11 +137,7 @@ pub fn part2(tiles: &[Tile]) -> u64 { + grid[Point::new(x1 - 1, y1 - 1)]; if expected == actual { - let [x1, y1] = tiles[i]; - let [x2, y2] = tiles[j]; - let dx = x1.abs_diff(x2) + 1; - let dy = y1.abs_diff(y2) + 1; - area = area.max(dx * dy); + area = area.max(box_area(&tiles[i], &tiles[j])); } } } @@ -89,6 +145,12 @@ pub fn part2(tiles: &[Tile]) -> u64 { area } +fn box_area(p1: &Tile, p2: &Tile) -> u64 { + let dx = p1[0].abs_diff(p2[0]) + 1; + let dy = p1[1].abs_diff(p2[1]) + 1; + dx * dy +} + fn shrink(tiles: &[Tile], index: usize) -> FastMap { let mut axis: Vec<_> = tiles.iter().map(|tile| tile[index]).collect(); axis.push(u64::MIN);