84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
use anyhow::Result;
|
|
use std::fs;
|
|
use std::collections::HashSet;
|
|
|
|
#[derive(Debug)]
|
|
struct Pair {
|
|
sensor: Coord,
|
|
beacon: Coord,
|
|
}
|
|
|
|
#[derive(Debug, Eq, Hash, PartialEq)]
|
|
struct Coord {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
|
|
impl Pair {
|
|
fn distance(self: &Self) -> i32 {
|
|
(self.sensor.x - self.beacon.x).abs() + (self.sensor.y - self.beacon.y).abs()
|
|
}
|
|
}
|
|
|
|
pub fn run() -> Result<()> {
|
|
#[cfg(not(feature = "test_input"))]
|
|
let file_contents = fs::read_to_string("day15.txt")?;
|
|
|
|
#[cfg(feature = "test_input")]
|
|
let file_contents = fs::read_to_string("tests/day15.txt")?;
|
|
|
|
let mut pairs: Vec<Pair> = Vec::with_capacity(25);
|
|
|
|
for line in file_contents.lines() {
|
|
let mut parts = line.split(": ");
|
|
let spart = parts.next().unwrap().strip_prefix("Sensor at ").unwrap();
|
|
let bpart = parts.next().unwrap().strip_prefix("closest beacon is at ").unwrap();
|
|
let mut scoords = spart.split(", ");
|
|
let sx = scoords.next().unwrap().strip_prefix("x=").unwrap().parse::<i32>().unwrap();
|
|
let sy = scoords.next().unwrap().strip_prefix("y=").unwrap().parse::<i32>().unwrap();
|
|
let mut bcoords = bpart.split(", ");
|
|
let bx = bcoords.next().unwrap().strip_prefix("x=").unwrap().parse::<i32>().unwrap();
|
|
let by = bcoords.next().unwrap().strip_prefix("y=").unwrap().parse::<i32>().unwrap();
|
|
pairs.push(Pair {
|
|
sensor: Coord { x: sx, y: sy },
|
|
beacon: Coord { x: bx, y: by },
|
|
});
|
|
}
|
|
|
|
#[cfg(not(feature = "test_input"))]
|
|
spots_taken_on_row(&pairs, 2000000);
|
|
|
|
#[cfg(feature = "test_input")]
|
|
spots_taken_on_row(&pairs, 10);
|
|
|
|
// println!("pairs {:?}", pairs);
|
|
Ok(())
|
|
}
|
|
|
|
fn spots_taken_on_row(pairs: &Vec<Pair>, row: i32) {
|
|
let mut c: HashSet<i32> = HashSet::new();
|
|
for p in pairs.iter() {
|
|
let d = p.distance();
|
|
if row > p.sensor.y && row - p.sensor.y > d {
|
|
continue;
|
|
} else if row < p.sensor.y && p.sensor.y - row > d {
|
|
continue;
|
|
}
|
|
let remaining_distance = d - (row - p.sensor.y).abs();
|
|
let minx = p.sensor.x - remaining_distance;
|
|
let maxx = p.sensor.x + remaining_distance;
|
|
// println!("{:?} distance {} from {}..={}", p.sensor, d, minx, maxx);
|
|
for x in minx..=maxx {
|
|
c.insert(x);
|
|
}
|
|
}
|
|
|
|
for p in pairs.iter() {
|
|
if p.beacon.y == row {
|
|
c.remove(&p.beacon.x);
|
|
}
|
|
}
|
|
|
|
println!("spots taken on row {} = {}", row, c.len());
|
|
}
|