2022 day15/rust: make part1 faster

This commit is contained in:
Xiretza 2022-12-15 21:55:27 +01:00
parent b9b46aab5b
commit 6fb08930bc

View file

@ -2,7 +2,7 @@
use std::io::stdin; use std::io::stdin;
use aoc::vec2::{Line, Vec2}; use aoc::{vec2::Vec2, SectionRange, UpToTwo};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Sensor { struct Sensor {
@ -56,31 +56,45 @@ fn main() {
]; ];
assert!(candidates.contains(&sensor.closest_beacon)); assert!(candidates.contains(&sensor.closest_beacon));
} }
let border_points = sensors.iter().filter_map(|sensor| {
sensor
.position
.on_y_with_manhattan_dist(2_000_000, sensor.beacon_distance())
});
let leftmost = border_points let mut ranges: Vec<_> = sensors
.clone()
.map(|(left, _right)| left)
.min()
.unwrap();
let rightmost = border_points.map(|(_left, right)| right).max().unwrap();
let count = Line {
start: leftmost,
end: rightmost,
}
.points()
.unwrap()
.filter(|&p| {
sensors
.iter() .iter()
.any(|s| p != s.closest_beacon && s.position.manhattan_dist(p) <= s.beacon_distance()) .flat_map(|sensor| {
let y = 2_000_000;
let Some((left, right)) = sensor
.position
.on_y_with_manhattan_dist(y, sensor.beacon_distance())
else {
return UpToTwo::Zero;
};
let range = SectionRange::try_new(left.x, right.x).unwrap();
if sensor.closest_beacon.y == y {
let beacon_pos = sensor.closest_beacon.y;
let beacon_pos = SectionRange::try_new(beacon_pos, beacon_pos).unwrap();
range - beacon_pos
} else {
UpToTwo::One(range)
}
}) })
.count(); .collect();
ranges.sort_unstable();
let mut covered = ranges.into_iter();
let mut count = 0;
let mut current_range = covered.next().unwrap();
for range in covered {
match current_range | range {
UpToTwo::Zero => unreachable!(),
UpToTwo::One(new) => current_range = new,
UpToTwo::Two(_old, new) => {
count += current_range.len().get();
current_range = new;
}
}
}
count += current_range.len().get();
println!("{:?}", count); println!("{:?}", count);
} }