[rs] Optimize 2022_16 part 1
This commit is contained in:
parent
a794e21840
commit
379ad232a4
1 changed files with 43 additions and 13 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
fn parse_valve(line: &str) -> (&str, u32, Vec<&str>) {
|
fn parse_valve(line: &str) -> (&str, u32, Vec<&str>) {
|
||||||
let (name, rest) = line
|
let (name, rest) = line
|
||||||
|
|
@ -74,6 +75,38 @@ impl OpenSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Dp1 {
|
||||||
|
valves: usize,
|
||||||
|
powers: usize,
|
||||||
|
elems: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dp1 {
|
||||||
|
fn new(valves: &[Valve], powerset: &[OpenSet]) -> Self {
|
||||||
|
let valves = valves.len();
|
||||||
|
let powers = powerset.len();
|
||||||
|
let elems = vec![0; valves * powers];
|
||||||
|
Self {
|
||||||
|
valves,
|
||||||
|
powers,
|
||||||
|
elems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, valve_id: usize, open: OpenSet) -> u32 {
|
||||||
|
self.elems[self.powers * valve_id + open.0 as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, valve_id: usize, open: OpenSet, score: u32) {
|
||||||
|
self.elems[self.powers * valve_id + open.0 as usize] = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.elems.fill(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn solve(input: String) {
|
pub fn solve(input: String) {
|
||||||
let valves = input.lines().map(parse_valve).collect::<Vec<_>>();
|
let valves = input.lines().map(parse_valve).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
@ -86,15 +119,8 @@ pub fn solve(input: String) {
|
||||||
// - The current valve
|
// - The current valve
|
||||||
// - The current set of open/closed valves
|
// - The current set of open/closed valves
|
||||||
|
|
||||||
let mut dp = HashMap::new();
|
let mut prev = Dp1::new(&valves, &powerset);
|
||||||
|
let mut curr = Dp1::new(&valves, &powerset);
|
||||||
// Initialize for end state
|
|
||||||
eprintln!("Minute 0");
|
|
||||||
for valve_id in 0..valves.len() {
|
|
||||||
for open in &powerset {
|
|
||||||
dp.insert((0_u32, valve_id, *open), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given valve v in minute t with set s, you can either...
|
// Given valve v in minute t with set s, you can either...
|
||||||
// - Go to another neighbouring valve v', points: points[v', t-1, s]
|
// - Go to another neighbouring valve v', points: points[v', t-1, s]
|
||||||
|
|
@ -102,26 +128,30 @@ pub fn solve(input: String) {
|
||||||
|
|
||||||
for minute in 1..=30 {
|
for minute in 1..=30 {
|
||||||
eprintln!("Minute {minute}");
|
eprintln!("Minute {minute}");
|
||||||
|
|
||||||
|
mem::swap(&mut curr, &mut prev);
|
||||||
|
curr.clear();
|
||||||
|
|
||||||
for (valve_id, valve) in valves.iter().enumerate() {
|
for (valve_id, valve) in valves.iter().enumerate() {
|
||||||
for open in &powerset {
|
for open in &powerset {
|
||||||
let mut score = valve
|
let mut score = valve
|
||||||
.next
|
.next
|
||||||
.iter()
|
.iter()
|
||||||
.map(|next_id| dp[&(minute - 1, *next_id, *open)])
|
.map(|next_id| prev.get(*next_id, *open))
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
if valve.rate > 0 && !open.is_open(valve_id) {
|
if valve.rate > 0 && !open.is_open(valve_id) {
|
||||||
let room_but_valve_open = dp[&(minute - 1, valve_id, open.open(valve_id))];
|
let room_but_valve_open = prev.get(valve_id, open.open(valve_id));
|
||||||
let pressure_until_end = (minute - 1) * valve.rate;
|
let pressure_until_end = (minute - 1) * valve.rate;
|
||||||
score = score.max(room_but_valve_open + pressure_until_end);
|
score = score.max(room_but_valve_open + pressure_until_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
dp.insert((minute, valve_id, *open), score);
|
curr.set(valve_id, *open, score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let part1 = dp[&(30, names["AA"], OpenSet::ALL_CLOSED)];
|
let part1 = curr.get(names["AA"], OpenSet::ALL_CLOSED);
|
||||||
println!("Part 1: {part1}");
|
println!("Part 1: {part1}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue