2022 day 16 refactor
This commit is contained in:
parent
e3321a08a8
commit
a581dd4f44
|
@ -99,49 +99,65 @@ fn release_bitmap(valves: &[Valve], bitmap: u64) -> u32 {
|
||||||
sum
|
sum
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn set_to_bitmap(set: &HashSet<usize>) -> u64 {
|
fn set_to_bitmap(set: &HashSet<usize>) -> u64 {
|
||||||
// let mut map = 0;
|
let mut map = 0;
|
||||||
// for &index in set {
|
for &index in set {
|
||||||
// map |= 1 << index
|
map |= 1 << index
|
||||||
// }
|
}
|
||||||
// map
|
map
|
||||||
// }
|
}
|
||||||
|
|
||||||
struct MoveState<'a> {
|
struct MoveState<'a> {
|
||||||
curr: usize,
|
current: usize,
|
||||||
next: usize,
|
|
||||||
time_left: u32,
|
time_left: u32,
|
||||||
closed: &'a HashSet<usize>,
|
closed: &'a HashSet<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> MoveState<'a> {
|
||||||
|
fn as_cache_key(&self) -> (usize, u32, u64) {
|
||||||
|
(self.current, self.time_left, set_to_bitmap(self.closed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn move_to_open(
|
fn move_to_open(
|
||||||
valves: &[Valve],
|
valves: &[Valve],
|
||||||
distances: &HashMap<(usize, usize), u32>,
|
distances: &HashMap<(usize, usize), u32>,
|
||||||
state: MoveState,
|
state: MoveState,
|
||||||
|
cache: &mut HashMap<(usize, u32, u64), u32>
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let distance = state.time_left.min(*distances.get(&(state.curr, state.next)).unwrap());
|
if state.time_left < 1 { return 0 };
|
||||||
if distance == state.time_left { return 0 };
|
let cached = cache.get(&state.as_cache_key());
|
||||||
let curr = state.next;
|
if cached.is_some() { return *cached.unwrap() }
|
||||||
|
|
||||||
let closed = { let mut closed = state.closed.clone(); closed.remove(&curr); closed };
|
let closed = { let mut closed = state.closed.clone(); closed.remove(&state.current); closed };
|
||||||
let time_left = state.time_left - distance - 1;
|
let time_left = state.time_left - 1;
|
||||||
let released = valves[curr].rate * time_left;
|
let released = valves[state.current].rate * time_left;
|
||||||
|
|
||||||
let max_next = closed.iter()
|
let max_next = closed.iter()
|
||||||
.map(|&next| move_to_open(valves, distances, MoveState { curr, next, time_left, closed: &closed }))
|
.filter_map(|¤t| {
|
||||||
|
let distance = distances[&(state.current, current)];
|
||||||
|
match time_left > distance + 1 {
|
||||||
|
true => Some(move_to_open(valves, distances, MoveState {
|
||||||
|
current,
|
||||||
|
time_left: time_left - distance,
|
||||||
|
closed: &closed
|
||||||
|
}, cache)),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
let result = released + max_next;
|
||||||
released + max_next
|
cache.insert(state.as_cache_key(), result);
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_max_for_start(valves: &[Valve], start: usize, limit: u32) -> u32 {
|
fn find_max_for_start(valves: &[Valve], start: usize, limit: u32) -> u32 {
|
||||||
move_to_open(&valves, &find_distances(&valves), MoveState {
|
move_to_open(&valves, &find_distances(&valves), MoveState {
|
||||||
curr: start,
|
current: start,
|
||||||
next: start,
|
|
||||||
time_left: limit + 1,
|
time_left: limit + 1,
|
||||||
closed: &closed_valves(valves)
|
closed: &closed_valves(valves)
|
||||||
})
|
}, &mut HashMap::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve1((map, data): &(HashMap<&str, usize>, Vec<Valve>)) -> u32 {
|
fn solve1((map, data): &(HashMap<&str, usize>, Vec<Valve>)) -> u32 {
|
||||||
|
|
Loading…
Reference in a new issue