Cache the polygon containement
This commit is contained in:
parent
3ba0a0b6c6
commit
8662ab104f
1 changed files with 53 additions and 19 deletions
|
|
@ -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 aoc_2025::{load, print_res};
|
||||||
use bstr::BString;
|
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<Point2, bool>,
|
||||||
|
) -> bool {
|
||||||
assert_ne!(a.x, b.x);
|
assert_ne!(a.x, b.x);
|
||||||
|
|
||||||
let min_x = a.x.min(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 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 {
|
for &y in y_values {
|
||||||
// Left corner
|
// Left corner
|
||||||
|
|
||||||
if !poly.contains(Point2 { x: min_x, y }) {
|
if !contains(Point2 { x: min_x, y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !poly.contains(Point2 { x: min_x + 1, y }) {
|
if !contains(Point2 { x: min_x + 1, y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,9 +224,9 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool {
|
||||||
.skip_while(|&&x| x <= min_x)
|
.skip_while(|&&x| x <= min_x)
|
||||||
.take_while(|&&x| x < max_x)
|
.take_while(|&&x| x < max_x)
|
||||||
{
|
{
|
||||||
if !poly.contains(Point2 { x, y })
|
if !contains(Point2 { x, y })
|
||||||
|| !poly.contains(Point2 { x: x - 1, y })
|
|| !contains(Point2 { x: x - 1, y })
|
||||||
|| !poly.contains(Point2 { x: x + 1, y })
|
|| !contains(Point2 { x: x + 1, y })
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -216,11 +234,11 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool {
|
||||||
|
|
||||||
// Right corner
|
// Right corner
|
||||||
|
|
||||||
if !poly.contains(Point2 { x: max_x, y }) {
|
if !contains(Point2 { x: max_x, y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !poly.contains(Point2 { x: max_x - 1, y }) {
|
if !contains(Point2 { x: max_x - 1, y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +246,12 @@ fn horizontal_edges_contained(poly: &Polygon, a: Point2, b: Point2) -> bool {
|
||||||
true
|
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<Point2, bool>,
|
||||||
|
) -> bool {
|
||||||
assert_ne!(a.y, b.y);
|
assert_ne!(a.y, b.y);
|
||||||
|
|
||||||
let min_y = a.y.min(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 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 {
|
for &x in x_values {
|
||||||
// Bottom corner
|
// Bottom corner
|
||||||
|
|
||||||
if !poly.contains(Point2 { x, y: min_y }) {
|
if !contains(Point2 { x, y: min_y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !poly.contains(Point2 { x, y: min_y + 1 }) {
|
if !contains(Point2 { x, y: min_y + 1 }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,9 +287,9 @@ fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool {
|
||||||
.skip_while(|&&y| y <= min_y)
|
.skip_while(|&&y| y <= min_y)
|
||||||
.take_while(|&&y| y < max_y)
|
.take_while(|&&y| y < max_y)
|
||||||
{
|
{
|
||||||
if !poly.contains(Point2 { x, y })
|
if !contains(Point2 { x, y })
|
||||||
|| !poly.contains(Point2 { x, y: y - 1 })
|
|| !contains(Point2 { x, y: y - 1 })
|
||||||
|| !poly.contains(Point2 { x, y: y + 1 })
|
|| !contains(Point2 { x, y: y + 1 })
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -265,11 +297,11 @@ fn vertical_edges_contain(poly: &Polygon, a: Point2, b: Point2) -> bool {
|
||||||
|
|
||||||
// Top corner
|
// Top corner
|
||||||
|
|
||||||
if !poly.contains(Point2 { x, y: max_y }) {
|
if !contains(Point2 { x, y: max_y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !poly.contains(Point2 { x, y: max_y - 1 }) {
|
if !contains(Point2 { x, y: max_y - 1 }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -283,6 +315,8 @@ pub fn part2(input: Parsed) {
|
||||||
|
|
||||||
let mut max_area = 0;
|
let mut max_area = 0;
|
||||||
|
|
||||||
|
let mut contains_cache = HashMap::new();
|
||||||
|
|
||||||
for (ia, &a) in poly.points().iter().enumerate() {
|
for (ia, &a) in poly.points().iter().enumerate() {
|
||||||
for &b in poly.points().iter().skip(ia + 1) {
|
for &b in poly.points().iter().skip(ia + 1) {
|
||||||
let area = rect_area(&a, &b);
|
let area = rect_area(&a, &b);
|
||||||
|
|
@ -293,11 +327,11 @@ pub fn part2(input: Parsed) {
|
||||||
|
|
||||||
assert!(area > 1);
|
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;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue