Cache the edge calculations
This commit is contained in:
parent
8662ab104f
commit
a8ee7f78f6
1 changed files with 46 additions and 2 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
hash::Hash,
|
||||||
ops::RangeInclusive,
|
ops::RangeInclusive,
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
@ -183,11 +184,27 @@ impl Polygon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InsertGuard<'a, K, V>(K, V, &'a mut HashMap<K, V>)
|
||||||
|
where
|
||||||
|
K: Hash + Eq + Copy,
|
||||||
|
V: Copy;
|
||||||
|
|
||||||
|
impl<'a, K, V> Drop for InsertGuard<'a, K, V>
|
||||||
|
where
|
||||||
|
K: Hash + Eq + Copy,
|
||||||
|
V: Copy,
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.2.insert(self.0, self.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn horizontal_edges_contained(
|
fn horizontal_edges_contained(
|
||||||
poly: &Polygon,
|
poly: &Polygon,
|
||||||
a: Point2,
|
a: Point2,
|
||||||
b: Point2,
|
b: Point2,
|
||||||
cache: &mut HashMap<Point2, bool>,
|
cache: &mut HashMap<Point2, bool>,
|
||||||
|
edge_cache: &mut HashMap<(u64, (u64, u64)), bool>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
assert_ne!(a.x, b.x);
|
assert_ne!(a.x, b.x);
|
||||||
|
|
||||||
|
|
@ -206,6 +223,13 @@ fn horizontal_edges_contained(
|
||||||
};
|
};
|
||||||
|
|
||||||
for &y in y_values {
|
for &y in y_values {
|
||||||
|
let key = (y, (min_x, max_x));
|
||||||
|
if let Some(&v) = edge_cache.get(&key) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
let guard = InsertGuard(key, false, edge_cache);
|
||||||
|
|
||||||
// Left corner
|
// Left corner
|
||||||
|
|
||||||
if !contains(Point2 { x: min_x, y }) {
|
if !contains(Point2 { x: min_x, y }) {
|
||||||
|
|
@ -241,6 +265,9 @@ fn horizontal_edges_contained(
|
||||||
if !contains(Point2 { x: max_x - 1, y }) {
|
if !contains(Point2 { x: max_x - 1, y }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::mem::forget(guard);
|
||||||
|
edge_cache.insert(key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
@ -251,6 +278,7 @@ fn vertical_edges_contain(
|
||||||
a: Point2,
|
a: Point2,
|
||||||
b: Point2,
|
b: Point2,
|
||||||
cache: &mut HashMap<Point2, bool>,
|
cache: &mut HashMap<Point2, bool>,
|
||||||
|
edge_cache: &mut HashMap<(u64, (u64, u64)), bool>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
assert_ne!(a.y, b.y);
|
assert_ne!(a.y, b.y);
|
||||||
|
|
||||||
|
|
@ -269,6 +297,13 @@ fn vertical_edges_contain(
|
||||||
};
|
};
|
||||||
|
|
||||||
for &x in x_values {
|
for &x in x_values {
|
||||||
|
let key = (x, (min_y, max_y));
|
||||||
|
if let Some(&v) = edge_cache.get(&key) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
let guard = InsertGuard(key, false, edge_cache);
|
||||||
|
|
||||||
// Bottom corner
|
// Bottom corner
|
||||||
|
|
||||||
if !contains(Point2 { x, y: min_y }) {
|
if !contains(Point2 { x, y: min_y }) {
|
||||||
|
|
@ -304,6 +339,9 @@ fn vertical_edges_contain(
|
||||||
if !contains(Point2 { x, y: max_y - 1 }) {
|
if !contains(Point2 { x, y: max_y - 1 }) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::mem::forget(guard);
|
||||||
|
edge_cache.insert(key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|
@ -316,6 +354,8 @@ pub fn part2(input: Parsed) {
|
||||||
let mut max_area = 0;
|
let mut max_area = 0;
|
||||||
|
|
||||||
let mut contains_cache = HashMap::new();
|
let mut contains_cache = HashMap::new();
|
||||||
|
let mut h_edge_cache = HashMap::new();
|
||||||
|
let mut v_edge_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) {
|
||||||
|
|
@ -327,11 +367,15 @@ pub fn part2(input: Parsed) {
|
||||||
|
|
||||||
assert!(area > 1);
|
assert!(area > 1);
|
||||||
|
|
||||||
if a.x != b.x && !horizontal_edges_contained(&poly, a, b, &mut contains_cache) {
|
if a.x != b.x
|
||||||
|
&& !horizontal_edges_contained(&poly, a, b, &mut contains_cache, &mut h_edge_cache)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.y != b.y && !vertical_edges_contain(&poly, a, b, &mut contains_cache) {
|
if a.y != b.y
|
||||||
|
&& !vertical_edges_contain(&poly, a, b, &mut contains_cache, &mut v_edge_cache)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue