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() .iter()
.map(|(left, _right)| left) .flat_map(|sensor| {
.min() let y = 2_000_000;
.unwrap(); let Some((left, right)) = sensor
let rightmost = border_points.map(|(_left, right)| right).max().unwrap(); .position
.on_y_with_manhattan_dist(y, sensor.beacon_distance())
else {
return UpToTwo::Zero;
};
let count = Line { let range = SectionRange::try_new(left.x, right.x).unwrap();
start: leftmost, if sensor.closest_beacon.y == y {
end: rightmost, 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)
}
})
.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;
}
}
} }
.points() count += current_range.len().get();
.unwrap()
.filter(|&p| {
sensors
.iter()
.any(|s| p != s.closest_beacon && s.position.manhattan_dist(p) <= s.beacon_distance())
})
.count();
println!("{:?}", count); println!("{:?}", count);
} }