1
0
Fork 0

Solve day 15

This commit is contained in:
Lars Martens 2022-12-15 23:42:37 +01:00
parent 57239c3080
commit 3e6bc1d0f6
Signed by: haselkern
GPG key ID: B5CF1F363C179AD4
5 changed files with 364 additions and 0 deletions

113
src/bin/15.rs Normal file
View file

@ -0,0 +1,113 @@
use aoc2022::*;
use indicatif::{ProgressBar, ProgressStyle};
use itertools::Itertools;
use rayon::iter::ParallelIterator;
use rayon::prelude::IntoParallelIterator;
use regex::Regex;
// const INPUT: &str = include_str!("../../input/15-test");
// const Y: i64 = 10;
// const MAX_COORD: i64 = 20;
const INPUT: &str = include_str!("../../input/15");
const Y: i64 = 2_000_000;
const MAX_COORD: i64 = 4_000_000;
fn main() {
solved_level_1(level1());
solved_level_2(level2());
}
fn level1() -> usize {
let sensors = input().collect_vec();
let (min, max) = sensors
.iter()
.flat_map(|s| [s.x - s.beacon_distance(), s.x + s.beacon_distance()])
.minmax()
.into_option()
.unwrap();
(min..=max)
.filter(|&x| {
sensors.iter().any(|s| {
s.distance(x, Y) <= s.beacon_distance() && !(x == s.beacon_x && Y == s.beacon_y)
})
})
.count()
}
fn level2() -> i64 {
// Efficient solution? 🚫
// Fancy progress bar? ✅
let style = ProgressStyle::with_template("[{bar:60}] {percent}%, ~{eta}")
.unwrap()
.progress_chars("❌🔎🔍🔎🔍🔎🔍❓");
let bar = ProgressBar::new(MAX_COORD as u64).with_style(style);
(0..=MAX_COORD)
.into_par_iter()
.flat_map(|y| {
bar.inc(1);
let mut x = 0;
// Push x to the right for each sensor range.
let mut moved = true;
while moved {
moved = false;
for sensor in input() {
if sensor.distance(x, y) <= sensor.beacon_distance() {
let rightmost = sensor.x + sensor.beacon_distance();
let y_diff = (sensor.y - y).abs();
let next_x = rightmost - y_diff;
x = x.max(next_x) + 1;
moved = true;
}
}
if x > MAX_COORD {
break;
}
}
if x <= MAX_COORD {
println!("Found x={x}, y={y}");
Some(x * 4000000 + y)
} else {
None
}
})
.find_any(|_| true)
.unwrap()
}
#[derive(Debug)]
struct Sensor {
x: i64,
y: i64,
beacon_x: i64,
beacon_y: i64,
}
impl Sensor {
fn distance(&self, x: i64, y: i64) -> i64 {
(self.x.abs_diff(x) + self.y.abs_diff(y)) as i64
}
fn beacon_distance(&self) -> i64 {
self.distance(self.beacon_x, self.beacon_y)
}
}
fn input() -> impl Iterator<Item = Sensor> {
let re =
Regex::new(r"^Sensor at x=(.+), y=(.+): closest beacon is at x=(.+), y=(.+)$").unwrap();
INPUT
.lines()
.map(move |line| re.captures(line).unwrap())
.map(|cap| Sensor {
x: cap.get(1).unwrap().as_str().parse().unwrap(),
y: cap.get(2).unwrap().as_str().parse().unwrap(),
beacon_x: cap.get(3).unwrap().as_str().parse().unwrap(),
beacon_y: cap.get(4).unwrap().as_str().parse().unwrap(),
})
}