diff --git a/src/bin/day9.rs b/src/bin/day9.rs index f30a8e7..79e3b4c 100644 --- a/src/bin/day9.rs +++ b/src/bin/day9.rs @@ -1,4 +1,8 @@ -use std::{collections::HashSet, ops::RangeInclusive, time::Instant}; +use std::{ + collections::{HashMap, HashSet}, + ops::RangeInclusive, + time::Instant, +}; use aoc_2025::{load, print_res}; use bstr::BString; @@ -179,7 +183,12 @@ impl Polygon { } } -fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool { +fn horizontal_edges_contained( + poly: &Polygon, + a: Point2, + b: Point2, + cache: &mut HashMap, +) -> bool { assert_ne!(a.x, b.x); let min_x = a.x.min(b.x); @@ -187,14 +196,23 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool { let y_values: &[u64] = if a.y == b.y { &[a.y] } else { &[a.y, b.y] }; + let mut contains = |point: Point2| match cache.get(&point) { + Some(&v) => v, + None => { + let v = poly.contains(point); + cache.insert(point, v); + v + } + }; + for &y in y_values { // Left corner - if !poly.contains(Point2 { x: min_x, y }) { + if !contains(Point2 { x: min_x, y }) { return false; } - if !poly.contains(Point2 { x: min_x + 1, y }) { + if !contains(Point2 { x: min_x + 1, y }) { return false; } @@ -206,9 +224,9 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool { .skip_while(|&&x| x <= min_x) .take_while(|&&x| x < max_x) { - if !poly.contains(Point2 { x, y }) - || !poly.contains(Point2 { x: x - 1, y }) - || !poly.contains(Point2 { x: x + 1, y }) + if !contains(Point2 { x, y }) + || !contains(Point2 { x: x - 1, y }) + || !contains(Point2 { x: x + 1, y }) { return false; } @@ -216,11 +234,11 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool { // Right corner - if !poly.contains(Point2 { x: max_x, y }) { + if !contains(Point2 { x: max_x, y }) { return false; } - if !poly.contains(Point2 { x: max_x - 1, y }) { + if !contains(Point2 { x: max_x - 1, y }) { return false; } } @@ -228,7 +246,12 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool { true } -fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool { +fn vertical_edges_contain( + poly: &Polygon, + a: Point2, + b: Point2, + cache: &mut HashMap, +) -> bool { assert_ne!(a.y, b.y); let min_y = a.y.min(b.y); @@ -236,14 +259,23 @@ fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool { let x_values: &[u64] = if a.x == b.x { &[a.x] } else { &[a.x, b.x] }; + let mut contains = |point: Point2| match cache.get(&point) { + Some(&v) => v, + None => { + let v = poly.contains(point); + cache.insert(point, v); + v + } + }; + for &x in x_values { // Bottom corner - if !poly.contains(Point2 { x, y: min_y }) { + if !contains(Point2 { x, y: min_y }) { return false; } - if !poly.contains(Point2 { x, y: min_y + 1 }) { + if !contains(Point2 { x, y: min_y + 1 }) { return false; } @@ -255,9 +287,9 @@ fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool { .skip_while(|&&y| y <= min_y) .take_while(|&&y| y < max_y) { - if !poly.contains(Point2 { x, y }) - || !poly.contains(Point2 { x, y: y - 1 }) - || !poly.contains(Point2 { x, y: y + 1 }) + if !contains(Point2 { x, y }) + || !contains(Point2 { x, y: y - 1 }) + || !contains(Point2 { x, y: y + 1 }) { return false; } @@ -265,11 +297,11 @@ fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool { // Top corner - if !poly.contains(Point2 { x, y: max_y }) { + if !contains(Point2 { x, y: max_y }) { return false; } - if !poly.contains(Point2 { x, y: max_y - 1 }) { + if !contains(Point2 { x, y: max_y - 1 }) { return false; } } @@ -283,6 +315,8 @@ pub fn part2(input: Parsed) { let mut max_area = 0; + let mut contains_cache = HashMap::new(); + for (ia, &a) in poly.points().iter().enumerate() { for &b in poly.points().iter().skip(ia + 1) { let area = rect_area(&a, &b); @@ -293,11 +327,11 @@ pub fn part2(input: Parsed) { assert!(area > 1); - if a.x != b.x && !horizontal_edges_contained(&poly, a, b) { + if a.x != b.x && !horizontal_edges_contained(&poly, a, b, &mut contains_cache) { continue; } - if a.y != b.y && !vertical_edges_contain(&poly, a, b) { + if a.y != b.y && !vertical_edges_contain(&poly, a, b, &mut contains_cache) { continue; }