[rs] Parallelize 2022_16 part 2
This commit is contained in:
parent
4f9de30212
commit
efaaef4e6a
3 changed files with 193 additions and 53 deletions
|
|
@ -1,6 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
|
||||
use rayon::prelude::{
|
||||
IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator,
|
||||
};
|
||||
|
||||
fn parse_valve(line: &str) -> (&str, u32, Vec<&str>) {
|
||||
let (name, rest) = line
|
||||
.strip_prefix("Valve ")
|
||||
|
|
@ -168,15 +172,57 @@ impl Dp2 {
|
|||
let id = self.powers * (self.valves * own_id + el_id) + open.0 as usize;
|
||||
self.elems[id]
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, own_id: usize, el_id: usize, open: OpenSet, score: u32) {
|
||||
let id = self.powers * (self.valves * own_id + el_id) + open.0 as usize;
|
||||
self.elems[id] = score;
|
||||
fn part_2_score(
|
||||
minute: u32,
|
||||
prev: &Dp2,
|
||||
own_id: usize,
|
||||
own_valve: &Valve,
|
||||
el_id: usize,
|
||||
el_valve: &Valve,
|
||||
open: OpenSet,
|
||||
) -> u32 {
|
||||
let mut score = 0;
|
||||
|
||||
// Both move
|
||||
for own_next in &own_valve.next {
|
||||
for el_next in &el_valve.next {
|
||||
score = score.max(prev.get(*own_next, *el_next, open));
|
||||
}
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.elems.fill(0);
|
||||
// I open valve
|
||||
let i_can_open = own_valve.rate > 0 && !open.is_open(own_id);
|
||||
if i_can_open {
|
||||
let open = open.open(own_id);
|
||||
for el_next in &el_valve.next {
|
||||
let room_but_valve_open = prev.get(own_id, *el_next, open);
|
||||
let pressure_until_end = (minute - 1) * own_valve.rate;
|
||||
score = score.max(room_but_valve_open + pressure_until_end);
|
||||
}
|
||||
}
|
||||
|
||||
// Elephant opens valve
|
||||
let el_can_open = el_valve.rate > 0 && !open.is_open(el_id);
|
||||
if el_can_open {
|
||||
let open = open.open(el_id);
|
||||
for own_next in &own_valve.next {
|
||||
let room_but_valve_open = prev.get(*own_next, el_id, open);
|
||||
let pressure_until_end = (minute - 1) * el_valve.rate;
|
||||
score = score.max(room_but_valve_open + pressure_until_end);
|
||||
}
|
||||
}
|
||||
|
||||
// Both open valve
|
||||
if own_id != el_id && i_can_open && el_can_open {
|
||||
let open = open.open(own_id).open(el_id);
|
||||
let room_but_valves_open = prev.get(own_id, el_id, open);
|
||||
let pressure_until_end = (minute - 1) * (own_valve.rate + el_valve.rate);
|
||||
score = score.max(room_but_valves_open + pressure_until_end);
|
||||
}
|
||||
|
||||
score
|
||||
}
|
||||
|
||||
fn solve_part_2(names: &HashMap<&str, usize>, valves: &[Valve], powerset: &[OpenSet]) -> u32 {
|
||||
|
|
@ -194,58 +240,33 @@ fn solve_part_2(names: &HashMap<&str, usize>, valves: &[Valve], powerset: &[Open
|
|||
// - I open valve, elephant moves
|
||||
// - I open valve, elephant opens valve (if not in same room)
|
||||
|
||||
let mut variations = vec![];
|
||||
for (own_id, own_valve) in valves.iter().enumerate() {
|
||||
for (el_id, el_valve) in valves.iter().enumerate() {
|
||||
for open in powerset {
|
||||
variations.push((own_id, own_valve, el_id, el_valve, open));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just to check whether the variations are in the correct order because I'm
|
||||
// zipping them to curr.elems later.
|
||||
for (i, (own_id, _, el_id, _, open)) in variations.iter().enumerate() {
|
||||
let id = curr.powers * (curr.valves * own_id + el_id) + open.0 as usize;
|
||||
assert_eq!(i, id);
|
||||
}
|
||||
|
||||
for minute in 1..=26 {
|
||||
eprintln!("Minute {minute}");
|
||||
|
||||
mem::swap(&mut curr, &mut prev);
|
||||
curr.clear();
|
||||
|
||||
for (own_id, own_valve) in valves.iter().enumerate() {
|
||||
for (el_id, el_valve) in valves.iter().enumerate() {
|
||||
for open in powerset {
|
||||
let mut score = 0;
|
||||
|
||||
// Both move
|
||||
for own_next in &own_valve.next {
|
||||
for el_next in &el_valve.next {
|
||||
score = score.max(prev.get(*own_next, *el_next, *open));
|
||||
}
|
||||
}
|
||||
|
||||
// I open valve
|
||||
let i_can_open = own_valve.rate > 0 && !open.is_open(own_id);
|
||||
if i_can_open {
|
||||
let open = open.open(own_id);
|
||||
for el_next in &el_valve.next {
|
||||
let room_but_valve_open = prev.get(own_id, *el_next, open);
|
||||
let pressure_until_end = (minute - 1) * own_valve.rate;
|
||||
score = score.max(room_but_valve_open + pressure_until_end);
|
||||
}
|
||||
}
|
||||
|
||||
// Elephant opens valve
|
||||
let el_can_open = el_valve.rate > 0 && !open.is_open(el_id);
|
||||
if el_can_open {
|
||||
let open = open.open(el_id);
|
||||
for own_next in &own_valve.next {
|
||||
let room_but_valve_open = prev.get(*own_next, el_id, open);
|
||||
let pressure_until_end = (minute - 1) * el_valve.rate;
|
||||
score = score.max(room_but_valve_open + pressure_until_end);
|
||||
}
|
||||
}
|
||||
|
||||
// Both open valve
|
||||
if own_id != el_id && i_can_open && el_can_open {
|
||||
let open = open.open(own_id).open(el_id);
|
||||
let room_but_valves_open = prev.get(own_id, el_id, open);
|
||||
let pressure_until_end = (minute - 1) * (own_valve.rate + el_valve.rate);
|
||||
score = score.max(room_but_valves_open + pressure_until_end);
|
||||
}
|
||||
|
||||
curr.set(own_id, el_id, *open, score);
|
||||
}
|
||||
}
|
||||
}
|
||||
curr.elems
|
||||
.par_iter_mut()
|
||||
.zip(variations.par_iter())
|
||||
.for_each(|(score, (own_id, own_valve, el_id, el_valve, open))| {
|
||||
*score = part_2_score(minute, &prev, *own_id, own_valve, *el_id, el_valve, **open);
|
||||
});
|
||||
}
|
||||
|
||||
curr.get(names["AA"], names["AA"], OpenSet::ALL_CLOSED)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue