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, next_row: Arc>) { 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); } } }