1
0
Fork 0

Optimize 09

This commit is contained in:
Lars Martens 2025-12-09 18:47:35 +01:00
parent c6d69e2fc2
commit 257c7e5cb6
Signed by: haselkern
GPG key ID: B5CF1F363C179AD4
3 changed files with 61 additions and 54 deletions

View file

@ -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();
}
}