Optimize 09
This commit is contained in:
parent
c6d69e2fc2
commit
257c7e5cb6
3 changed files with 61 additions and 54 deletions
|
|
@ -1,8 +1,7 @@
|
|||
use aoc::*;
|
||||
use derive_more::Deref;
|
||||
use glam::I64Vec2;
|
||||
use itertools::Itertools;
|
||||
use std::cmp::Reverse;
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const INPUT: &str = include_str!("../../input/09");
|
||||
|
|
@ -45,19 +44,19 @@ fn part2(input: &str) -> u64 {
|
|||
.iter()
|
||||
.copied()
|
||||
.tuple_combinations()
|
||||
.par_bridge()
|
||||
.map(Rect::from)
|
||||
.sorted_by_key(|r| {
|
||||
let area = r.uncompress(&uncompress).area();
|
||||
Reverse(area)
|
||||
})
|
||||
.find(|&r| polygon.contains_rect(r))
|
||||
.filter(|&r| polygon.contains_rect(r))
|
||||
.map(|r| r.uncompress(&uncompress).area())
|
||||
.max()
|
||||
.unwrap()
|
||||
.uncompress(&uncompress)
|
||||
.area()
|
||||
}
|
||||
|
||||
struct Polygon {
|
||||
points: Vec<I64Vec2>,
|
||||
/// Contains vertical lines sorted by their x value in ascending order.
|
||||
/// This is important for contains_point, as that assumes the lines are in this order.
|
||||
/// This dramatically speeds up the raycast in contains_point, as the ray is cast in positive x direction.
|
||||
cached_vertical_lines: Vec<Line>,
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +71,7 @@ impl Polygon {
|
|||
fn parse(input: &str) -> Self {
|
||||
let mut polygon = Self {
|
||||
points: input.lines().map(parse_line).collect(),
|
||||
cached_vertical_lines: vec![],
|
||||
cached_vertical_lines: Default::default(),
|
||||
};
|
||||
polygon.cache_vertical_lines();
|
||||
polygon
|
||||
|
|
@ -127,19 +126,20 @@ impl Polygon {
|
|||
let xs = self
|
||||
.cached_vertical_lines
|
||||
.iter()
|
||||
.take_while(|line| line.0.x < p.x)
|
||||
.filter(|l| {
|
||||
let ymin = l.0.y.min(l.1.y);
|
||||
let ymax = l.0.y.max(l.1.y);
|
||||
ymin <= p.y && p.y <= ymax
|
||||
})
|
||||
.flat_map(|l| [l.0.x])
|
||||
.filter(|&x| x < p.x)
|
||||
.map(|l| l.0.x)
|
||||
.chain([p.x])
|
||||
.sorted();
|
||||
|
||||
let line = |p| {
|
||||
let line_with = |p: I64Vec2| {
|
||||
self.cached_vertical_lines
|
||||
.iter()
|
||||
.take_while(|line| line.0.x <= p.x)
|
||||
.find(|line| line.contains(p))
|
||||
.copied()
|
||||
};
|
||||
|
|
@ -149,7 +149,7 @@ impl Polygon {
|
|||
|
||||
for x in xs {
|
||||
let check = I64Vec2::new(x, p.y);
|
||||
if let Some(line) = line(check) {
|
||||
if let Some(line) = line_with(check) {
|
||||
winding = line.winding();
|
||||
on_line = true;
|
||||
} else {
|
||||
|
|
@ -160,19 +160,17 @@ impl Polygon {
|
|||
winding < 0 || on_line
|
||||
}
|
||||
|
||||
fn vertical_lines(&self) -> Vec<Line> {
|
||||
self.points
|
||||
fn cache_vertical_lines(&mut self) {
|
||||
self.cached_vertical_lines = self
|
||||
.points
|
||||
.iter()
|
||||
.chain(self.points.first()) // close the loop
|
||||
.copied()
|
||||
.tuple_windows()
|
||||
.map(|(a, b)| Line(a, b))
|
||||
.filter(|l| l.is_vertical())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn cache_vertical_lines(&mut self) {
|
||||
self.cached_vertical_lines = self.vertical_lines();
|
||||
.sorted_by_key(|line| line.0.x)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue