use std::{ sync::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, }, thread, }; use aoc22::{day16, util}; pub fn main() { let valves = Arc::new(day16::parse_valves(&util::parse_input())); let dists = Arc::new(day16::calc_dists(&valves)); let state = day16::State::new(&valves); let possible_states = Arc::new(Mutex::new(Vec::new())); possible_states.lock().unwrap().push(state); let lower_bound = Arc::new(AtomicUsize::new(0)); let mut handles = Vec::new(); for _ in 0..16 { let s = possible_states.clone(); let l = lower_bound.clone(); let v = valves.clone(); let d = dists.clone(); handles.push(thread::spawn(move || check_states(s, l, v, d))); } for handle in handles { handle.join().unwrap(); } println!( "Most pressure released is {}", lower_bound.load(Ordering::Relaxed) ); } pub fn check_states( possible_states: Arc>>, lower_bound: Arc, valves: Arc>, dists: Arc>>, ) { let mut i = 0; loop { i += 1; let state = { possible_states.lock().unwrap().pop() }; if state.is_none() { break; } let state = state.unwrap(); if state.finished() { let score = state.lower_bound(); dbg!(score); lower_bound.fetch_max(score, Ordering::Relaxed); } else { let x = day16::possible_actions(&state, &valves, &dists); // let x = state.possible_actions(&valves, &dists); // let state_upper = state.upper_bound(&valves, &dists); for action in x { let action_upper = action.upper_bound(&valves, &dists); // assert!(action_upper <= state_upper); if action_upper > lower_bound.load(Ordering::Relaxed) { possible_states.lock().unwrap().push(action); } } } } dbg!(i); }