mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Implement 2022 day 15 part 2
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::Add;
|
||||
use std::ops::Div;
|
||||
use std::ops::Index;
|
||||
use std::ops::IndexMut;
|
||||
use std::ops::Sub;
|
||||
@@ -202,6 +203,14 @@ impl Sub<Self> for Vec2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<i32> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: i32) -> Self::Output {
|
||||
Self(self.0.map(|v| v / rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Vec2 {
|
||||
type Output = i32;
|
||||
|
||||
|
||||
@@ -18,6 +18,22 @@ use crate::common::Vec2;
|
||||
struct Beacon {
|
||||
pos: Vec2,
|
||||
closest: Vec2,
|
||||
range: i32,
|
||||
}
|
||||
|
||||
impl Beacon {
|
||||
pub fn can_contain_unseen(&self, lower: Vec2, upper: Vec2) -> bool {
|
||||
let corners = [
|
||||
lower,
|
||||
upper,
|
||||
Vec2([lower[0], upper[1]]),
|
||||
Vec2([upper[0], lower[1]]),
|
||||
];
|
||||
|
||||
corners
|
||||
.into_iter()
|
||||
.any(|c| (c - self.pos).l1() > self.range)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pos(input: &[u8]) -> IResult<&[u8], Vec2> {
|
||||
@@ -34,7 +50,11 @@ fn parse_beacons(input: &[u8]) -> IResult<&[u8], Vec<Beacon>> {
|
||||
preceded(tag("Sensor at "), parse_pos),
|
||||
preceded(tag(": closest beacon is at "), parse_pos),
|
||||
),
|
||||
|(pos, closest)| Beacon { pos, closest },
|
||||
|(pos, closest)| Beacon {
|
||||
pos,
|
||||
closest,
|
||||
range: (pos - closest).l1(),
|
||||
},
|
||||
);
|
||||
|
||||
many0(terminated(parse_beacon, newline))(input)
|
||||
@@ -51,8 +71,7 @@ fn part1_generic<const Y: i32>(input: &[u8]) -> Result<String> {
|
||||
let mut on_line = AHashSet::new();
|
||||
|
||||
for beacon in beacons {
|
||||
let distance = (beacon.closest - beacon.pos).l1();
|
||||
let horizontal_distance = distance - (beacon.pos[1] - Y).abs();
|
||||
let horizontal_distance = beacon.range - (beacon.pos[1] - Y).abs();
|
||||
|
||||
if horizontal_distance >= 0 {
|
||||
not_blocking_yet.push(Reverse((
|
||||
@@ -92,8 +111,53 @@ pub fn part1(input: &[u8]) -> Result<String> {
|
||||
part1_generic::<2000000>(input)
|
||||
}
|
||||
|
||||
pub fn part2(_input: &[u8]) -> Result<String> {
|
||||
anyhow::bail!("not implemented")
|
||||
fn part2_generic<const MAX: i32>(input: &[u8]) -> Result<String> {
|
||||
let beacons = parse_input(input, parse_beacons)?;
|
||||
|
||||
fn find_unseen<const MAX: i32>(beacons: &[Beacon]) -> Result<Vec2> {
|
||||
let mut todo = vec![(Vec2([0, 0]), Vec2([MAX, MAX]))];
|
||||
|
||||
while let Some((lower, upper)) = todo.pop() {
|
||||
if lower == upper {
|
||||
if beacons
|
||||
.iter()
|
||||
.all(|beacon| (beacon.pos - lower).l1() > beacon.range)
|
||||
{
|
||||
return Ok(lower);
|
||||
}
|
||||
} else {
|
||||
let mid = (lower + upper) / 2;
|
||||
|
||||
let quads = [
|
||||
(lower, mid),
|
||||
(Vec2([lower[0], mid[1] + 1]), Vec2([mid[0], upper[1]])),
|
||||
(Vec2([mid[0] + 1, lower[1]]), Vec2([upper[0], mid[1]])),
|
||||
(Vec2([mid[0] + 1, mid[1] + 1]), upper),
|
||||
];
|
||||
|
||||
for (lower_new, upper_new) in quads {
|
||||
if lower_new[0] > upper_new[0] || lower_new[1] > upper_new[1] {
|
||||
// Empty quad in quad tree, skip
|
||||
} else if beacons
|
||||
.iter()
|
||||
.all(|beacon| beacon.can_contain_unseen(lower_new, upper_new))
|
||||
{
|
||||
todo.push((lower_new, upper_new));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::bail!("Did not find position")
|
||||
}
|
||||
|
||||
let Vec2([x, y]) = find_unseen::<MAX>(&beacons)?;
|
||||
|
||||
Ok((i64::from(x) * 4000000 + i64::from(y)).to_string())
|
||||
}
|
||||
|
||||
pub fn part2(input: &[u8]) -> Result<String> {
|
||||
part2_generic::<4000000>(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -106,4 +170,9 @@ mod tests {
|
||||
fn sample_part1() {
|
||||
assert_eq!(part1_generic::<10>(SAMPLE).unwrap(), "26");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
assert_eq!(part2_generic::<20>(SAMPLE).unwrap(), "56000011");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user