-
Notifications
You must be signed in to change notification settings - Fork 0
/
day15_2.rs
103 lines (87 loc) · 2.61 KB
/
day15_2.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use itertools::Itertools;
use std::{ops::RangeInclusive, str::FromStr};
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
struct Coord {
x: isize,
y: isize,
}
#[derive(Debug)]
struct Sensor {
x: isize,
y: isize,
closest_beacon: Coord,
}
impl FromStr for Sensor {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (sensor_info, beacon_info) = s.split_once(":").unwrap();
let (sx, sy) = sensor_info.split_once(", ").unwrap();
let (bx, by) = beacon_info.split_once(", ").unwrap();
Ok(Sensor {
x: sx.parse().unwrap(),
y: sy.parse().unwrap(),
closest_beacon: Coord {
x: bx.parse().unwrap(),
y: by.parse().unwrap(),
},
})
}
}
impl Sensor {
fn manhattan_distance(&self, other: &Coord) -> isize {
(self.x - other.x).abs() + (self.y - other.y).abs()
}
fn beacon_range_at_row(&self, desired_row: isize) -> Option<RangeInclusive<isize>> {
let radius = self.manhattan_distance(&self.closest_beacon);
let offset = radius - (self.y - desired_row).abs();
if offset < 0 {
return None;
}
Some(self.x - offset..=self.x + offset)
}
}
fn normalize_ranges(sensors: &Vec<Sensor>, desired_row: isize) -> Vec<RangeInclusive<isize>> {
let mut x_ranges: Vec<RangeInclusive<isize>> = sensors
.iter()
.filter_map(|s| s.beacon_range_at_row(desired_row))
.collect();
x_ranges.sort_by_key(|r| *r.start());
x_ranges
.into_iter()
.coalesce(|a, b| {
if b.start() - 1 <= *a.end() {
if b.end() > a.end() {
Ok(*a.start()..=*b.end())
} else {
Ok(a)
}
} else {
Err((a, b))
}
})
.collect::<Vec<_>>()
}
fn main() {
let input = include_str!("../inputs/day15.txt");
let sensors = input
.lines()
.map(|l| {
l.replace("Sensor at ", "")
.replace(" closest beacon is at ", "")
.replace("x=", "")
.replace("y=", "")
})
.map(|l| l.parse::<Sensor>().unwrap())
.collect::<Vec<_>>();
let beacon_bound = 4_000_000;
let mut ans: usize = 0;
for y in 0..=beacon_bound {
let ranges_at_row = normalize_ranges(&sensors, y);
if ranges_at_row.len() > 1 {
let x = ranges_at_row.first().unwrap().end() + 1;
ans = (x * beacon_bound + y) as usize;
break;
}
}
println!("{}", ans);
}