71 lines
1.8 KiB
Rust
71 lines
1.8 KiB
Rust
use std::{
|
|
sync::{Arc, Mutex},
|
|
thread,
|
|
};
|
|
|
|
use aoc22::{day15, util};
|
|
use itertools::Itertools;
|
|
|
|
const COORD_MAX: isize = 4000000;
|
|
const NUM_THREADS: usize = 16;
|
|
|
|
pub fn main() {
|
|
let sensors = Arc::new(day15::parse_sensors(&util::parse_input()));
|
|
|
|
let mut handles = vec![];
|
|
let next_row = Arc::new(Mutex::new(0));
|
|
|
|
for _ in 0..NUM_THREADS {
|
|
let sensors = sensors.clone();
|
|
let next_row = next_row.clone();
|
|
let handle = thread::spawn(move || find_possible(&sensors, next_row));
|
|
handles.push(handle);
|
|
}
|
|
|
|
for handle in handles {
|
|
handle.join().unwrap();
|
|
}
|
|
}
|
|
|
|
pub fn find_possible(sensors: &Vec<day15::Sensor>, next_row: Arc<Mutex<isize>>) {
|
|
loop {
|
|
let row = {
|
|
let mut handle = next_row.lock().unwrap();
|
|
let result = *handle;
|
|
if result > COORD_MAX {
|
|
return;
|
|
}
|
|
*handle += 1;
|
|
result
|
|
};
|
|
|
|
let covered = sensors
|
|
.iter()
|
|
.map(|s| s.covered(row))
|
|
.filter(|r| !r.is_empty())
|
|
.sorted_by_key(|r| *r.start());
|
|
|
|
let mut max_x = isize::MIN;
|
|
for range in covered {
|
|
let (min, max) = range.into_inner();
|
|
if min == max_x + 2 {
|
|
let x = max_x + 1;
|
|
println!(
|
|
"x = {}, y = {}, tuning freq = {}",
|
|
x,
|
|
row,
|
|
x * 4000000 + row
|
|
)
|
|
} else if max_x != isize::MIN && min > max_x + 2 {
|
|
panic!(
|
|
"More than one coordinate free in row {}: {}..{}",
|
|
row,
|
|
max_x + 1,
|
|
min - 1
|
|
);
|
|
}
|
|
max_x = max_x.max(max);
|
|
}
|
|
}
|
|
}
|