Day 16, part 1 solved

This commit is contained in:
jazzpi
2022-12-21 19:33:17 +01:00
parent 0279edb249
commit 95e4095f32
2 changed files with 46 additions and 105 deletions

View File

@ -8,6 +8,8 @@ use itertools::Itertools;
use lazy_static::lazy_static;
use regex::Regex;
use crate::util;
const TOTAL_TIME: usize = 30;
#[derive(Debug, Clone)]
@ -86,6 +88,7 @@ pub struct State {
pub pressure_released: usize,
interesting: HashSet<usize>,
history: Vec<usize>,
}
impl State {
@ -102,35 +105,14 @@ impl State {
time_remaining: TOTAL_TIME,
pressure_released: 0,
interesting,
history: vec![0],
}
}
}
pub fn finished(&self) -> bool {
self.time_remaining == 0 || self.interesting.is_empty()
}
pub fn lower_bound(&self) -> usize {
self.pressure_released + self.flow_rate * self.time_remaining
}
pub fn upper_bound(&self, valves: &Vec<Valve>, dists: &Vec<Vec<usize>>) -> usize {
let mut additional_flow = 0;
for i in &self.interesting {
let i = i.clone();
if (self.opened & (1 << i)) != 0 {
continue;
}
let dist = dists[self.location][i];
if dist < self.time_remaining {
let flow = valves[i].flow_rate;
additional_flow += flow * (self.time_remaining - dist - 1);
}
}
self.lower_bound() + additional_flow
}
pub fn possible_actions(&self, valves: &Vec<Valve>, dists: &Vec<Vec<usize>>) -> Vec<State> {
type ExtraArgs<'a> = (&'a Vec<Valve>, &'a Vec<Vec<usize>>);
impl util::BnBState<ExtraArgs<'_>> for State {
fn possible_actions(&self, (valves, dists): &ExtraArgs) -> Vec<State> {
assert!(!self.finished());
let mut result = Vec::new();
@ -158,11 +140,42 @@ impl State {
moved.location = i;
moved.pressure_released += moved.flow_rate * dist;
moved.time_remaining -= dist;
moved.history.push(i);
result.push(moved);
}
let mut do_nothing = self.clone();
do_nothing.pressure_released += do_nothing.flow_rate * self.time_remaining;
do_nothing.time_remaining = 0;
result.push(do_nothing);
result
}
fn finished(&self) -> bool {
self.time_remaining == 0 || self.interesting.is_empty()
}
fn lower_bound(&self, _: &ExtraArgs) -> usize {
self.pressure_released + self.flow_rate * self.time_remaining
}
fn upper_bound(&self, (valves, dists): &ExtraArgs) -> usize {
let mut additional_flow = 0;
for i in &self.interesting {
let i = i.clone();
if (self.opened & (1 << i)) != 0 {
continue;
}
let dist = dists[self.location][i];
if dist < self.time_remaining {
let flow = valves[i].flow_rate;
additional_flow += flow * (self.time_remaining - dist - 1);
}
}
self.lower_bound(&(valves, dists)) + additional_flow
}
}
impl Hash for State {
@ -184,19 +197,3 @@ impl PartialEq for State {
}
impl Eq for State {}
pub fn possible_actions(state: &State, valves: &Vec<Valve>, dists: &Vec<Vec<usize>>) -> Vec<State> {
lazy_static! {
static ref CACHE: Mutex<HashMap<State, Vec<State>>> = Mutex::new(HashMap::new());
}
let actions = { CACHE.lock().unwrap().get(state).cloned() };
if let Some(actions) = actions {
// assert_eq!(actions, state.possible_actions(valves, dists));
actions.clone()
} else {
let mut cache = CACHE.lock().unwrap();
cache.insert(state.clone(), state.possible_actions(valves, dists));
cache[state].clone()
}
}