diff --git a/2022/day15/rust/src/main.rs b/2022/day15/rust/src/main.rs index 6111147..138ddef 100644 --- a/2022/day15/rust/src/main.rs +++ b/2022/day15/rust/src/main.rs @@ -2,7 +2,7 @@ use std::io::stdin; -use aoc::vec2::{Line, Vec2}; +use aoc::{vec2::Vec2, SectionRange, UpToTwo}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct Sensor { @@ -56,31 +56,45 @@ fn main() { ]; 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 - .clone() - .map(|(left, _right)| left) - .min() - .unwrap(); - let rightmost = border_points.map(|(_left, right)| right).max().unwrap(); + let mut ranges: Vec<_> = sensors + .iter() + .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 count = Line { - start: leftmost, - end: rightmost, + 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) + } + }) + .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() - .unwrap() - .filter(|&p| { - sensors - .iter() - .any(|s| p != s.closest_beacon && s.position.manhattan_dist(p) <= s.beacon_distance()) - }) - .count(); + count += current_range.len().get(); println!("{:?}", count); }