2022 Day 15: Part 1
This commit is contained in:
parent
2aefc33bc2
commit
dc88470d1c
1 changed files with 101 additions and 0 deletions
101
2022/src/bin/day15.rs
Normal file
101
2022/src/bin/day15.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
const INPUT: &str = include_str!("../../input/day15.txt");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{}", part1(INPUT, 2_000_000));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct Pos {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Pos {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pos {
|
||||||
|
fn new(x: i32, y: i32) -> Self {
|
||||||
|
Self { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distance(&self, other: Pos) -> i32 {
|
||||||
|
let dx = self.x - other.x;
|
||||||
|
let dy = self.y - other.y;
|
||||||
|
dx.abs() + dy.abs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
struct Sensor {
|
||||||
|
pos: Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
struct Beacon {
|
||||||
|
pos: Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str, yy: i32) -> usize {
|
||||||
|
let pairs: Vec<(Sensor, Beacon)> = aoc::lines(input).map(parse_line).collect();
|
||||||
|
|
||||||
|
let relevant: Vec<(Sensor, Beacon)> = pairs
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.filter(|(s, b)| {
|
||||||
|
let d_cover = s.pos.distance(b.pos);
|
||||||
|
let d_line = s.pos.distance(Pos::new(s.pos.x, yy));
|
||||||
|
d_line <= d_cover
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut coverage: HashSet<Pos> = HashSet::new();
|
||||||
|
|
||||||
|
for (s, b) in relevant {
|
||||||
|
let d_cover = s.pos.distance(b.pos);
|
||||||
|
let d_line = s.pos.distance(Pos::new(s.pos.x, yy));
|
||||||
|
let w_line = d_cover - d_line;
|
||||||
|
|
||||||
|
let x = s.pos.x;
|
||||||
|
for dx in 0..=w_line {
|
||||||
|
coverage.insert(Pos::new(x + dx, yy));
|
||||||
|
coverage.insert(Pos::new(x - dx, yy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, b) in pairs {
|
||||||
|
coverage.remove(&b.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
coverage.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(line: &str) -> (Sensor, Beacon) {
|
||||||
|
let re = Regex::new(
|
||||||
|
r"Sensor at x=(?P<sx>.*), y=(?P<sy>.*): closest beacon is at x=(?P<bx>.*), y=(?P<by>.*)",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let caps = re.captures(line).unwrap();
|
||||||
|
|
||||||
|
(
|
||||||
|
Sensor {
|
||||||
|
pos: Pos {
|
||||||
|
x: caps.name("sx").unwrap().as_str().parse().unwrap(),
|
||||||
|
y: caps.name("sy").unwrap().as_str().parse().unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Beacon {
|
||||||
|
pos: Pos {
|
||||||
|
x: caps.name("bx").unwrap().as_str().parse().unwrap(),
|
||||||
|
y: caps.name("by").unwrap().as_str().parse().unwrap(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue