[rs] Solve 2022_16 part 1

This commit is contained in:
Joscha 2022-12-16 13:06:09 +01:00
parent cc8fe30a36
commit a794e21840
7 changed files with 194 additions and 0 deletions

51
inputs/2022/2022_16.input Normal file
View file

@ -0,0 +1,51 @@
Valve NV has flow rate=5; tunnels lead to valves ZV, CG, YB, HX, OY
Valve NU has flow rate=6; tunnels lead to valves DA, MA, OA, DK
Valve VU has flow rate=0; tunnels lead to valves PS, FX
Valve JW has flow rate=0; tunnels lead to valves AA, MD
Valve RI has flow rate=0; tunnels lead to valves OY, DG
Valve DG has flow rate=9; tunnels lead to valves TG, RI, DF, EV, KW
Valve PH has flow rate=7; tunnels lead to valves KW, OW, LT, LZ
Valve KZ has flow rate=12; tunnels lead to valves ET, QV, CK, MS
Valve IX has flow rate=0; tunnels lead to valves TS, DO
Valve MS has flow rate=0; tunnels lead to valves LZ, KZ
Valve IL has flow rate=0; tunnels lead to valves DO, ET
Valve EJ has flow rate=20; tunnels lead to valves AV, JY
Valve DK has flow rate=0; tunnels lead to valves NU, CG
Valve YB has flow rate=0; tunnels lead to valves NV, PS
Valve OA has flow rate=0; tunnels lead to valves YA, NU
Valve DA has flow rate=0; tunnels lead to valves NU, RG
Valve KO has flow rate=0; tunnels lead to valves AA, TG
Valve RG has flow rate=4; tunnels lead to valves DF, DA, ZV, MD, LB
Valve MA has flow rate=0; tunnels lead to valves AA, NU
Valve OW has flow rate=0; tunnels lead to valves DO, PH
Valve KW has flow rate=0; tunnels lead to valves DG, PH
Valve DO has flow rate=14; tunnels lead to valves IX, IL, CZ, OW
Valve DF has flow rate=0; tunnels lead to valves RG, DG
Valve TG has flow rate=0; tunnels lead to valves DG, KO
Valve LB has flow rate=0; tunnels lead to valves RG, FX
Valve HX has flow rate=0; tunnels lead to valves AA, NV
Valve GB has flow rate=0; tunnels lead to valves AV, XK
Valve CG has flow rate=0; tunnels lead to valves DK, NV
Valve LT has flow rate=0; tunnels lead to valves AO, PH
Valve FX has flow rate=23; tunnels lead to valves LB, HY, VU
Valve ET has flow rate=0; tunnels lead to valves IL, KZ
Valve CK has flow rate=0; tunnels lead to valves UX, KZ
Valve LZ has flow rate=0; tunnels lead to valves PH, MS
Valve YA has flow rate=17; tunnels lead to valves JY, OA
Valve TS has flow rate=0; tunnels lead to valves NO, IX
Valve NO has flow rate=8; tunnel leads to valve TS
Valve XK has flow rate=24; tunnel leads to valve GB
Valve PS has flow rate=18; tunnels lead to valves EV, VU, YB
Valve AA has flow rate=0; tunnels lead to valves JW, HX, MA, KO
Valve MD has flow rate=0; tunnels lead to valves JW, RG
Valve JM has flow rate=19; tunnels lead to valves QV, HY, AO
Valve AV has flow rate=0; tunnels lead to valves EJ, GB
Valve AO has flow rate=0; tunnels lead to valves JM, LT
Valve JY has flow rate=0; tunnels lead to valves YA, EJ
Valve OY has flow rate=0; tunnels lead to valves NV, RI
Valve UX has flow rate=13; tunnels lead to valves CZ, CK
Valve HY has flow rate=0; tunnels lead to valves JM, FX
Valve EV has flow rate=0; tunnels lead to valves PS, DG
Valve CZ has flow rate=0; tunnels lead to valves UX, DO
Valve ZV has flow rate=0; tunnels lead to valves NV, RG
Valve QV has flow rate=0; tunnels lead to valves JM, KZ

View file

@ -0,0 +1,2 @@
Part 1: 1923
Part 2: ???

View file

@ -66,6 +66,7 @@ days! {
Y2022D13: "2022_13" => y2022::d13::solve,
Y2022D14: "2022_14" => y2022::d14::solve,
Y2022D15: "2022_15" => y2022::d15::solve,
Y2022D16: "2022_16" => y2022::d16::solve,
}
#[derive(Parser)]

View file

@ -13,3 +13,4 @@ pub mod d12;
pub mod d13;
pub mod d14;
pub mod d15;
pub mod d16;

127
rs/src/y2022/d16.rs Normal file
View file

@ -0,0 +1,127 @@
use std::collections::HashMap;
fn parse_valve(line: &str) -> (&str, u32, Vec<&str>) {
let (name, rest) = line
.strip_prefix("Valve ")
.unwrap()
.split_once(" has flow rate=")
.unwrap();
let (rate, rest) = rest.split_once("; ").unwrap();
let next = rest
.strip_prefix("tunnel leads to valve ")
.or_else(|| rest.strip_prefix("tunnels lead to valves "))
.unwrap()
.split(", ")
.collect::<Vec<_>>();
(name, rate.parse().unwrap(), next)
}
#[derive(Debug)]
struct Valve {
rate: u32,
next: Vec<usize>,
}
fn prepare_valves<'a>(
mut valves: Vec<(&'a str, u32, Vec<&str>)>,
) -> (HashMap<&'a str, usize>, Vec<Valve>) {
// All valves with a nonzero rate should come before the ones with a rate of
// zero. This will help with our valve bitset later.
valves.sort_by_key(|(_, rate, _)| *rate);
valves.reverse();
let names = valves
.iter()
.enumerate()
.map(|(i, (n, _, _))| (*n, i))
.collect::<HashMap<_, _>>();
let valves = valves
.into_iter()
.map(|(_, rate, next)| {
let next = next.into_iter().map(|n| names[n]).collect();
Valve { rate, next }
})
.collect::<Vec<_>>();
(names, valves)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct OpenSet(u64);
impl OpenSet {
const ALL_CLOSED: Self = Self(0);
/// The powerset of the set of all open valves.
fn powerset(valves: &[Valve]) -> Vec<Self> {
assert!(valves.len() <= 63);
let first_zero_rate = valves
.iter()
.position(|v| v.rate == 0)
.unwrap_or(valves.len());
let until = 2_u64.pow(first_zero_rate as u32);
(0..until).map(Self).collect::<Vec<_>>()
}
fn is_open(&self, valve_id: usize) -> bool {
assert!(valve_id < 63);
self.0 & (1 << valve_id) != 0
}
fn open(&self, valve_id: usize) -> Self {
assert!(valve_id < 63);
Self(self.0 | (1 << valve_id))
}
}
pub fn solve(input: String) {
let valves = input.lines().map(parse_valve).collect::<Vec<_>>();
let (names, valves) = prepare_valves(valves);
let powerset = OpenSet::powerset(&valves);
eprintln!("Powerset has size {}", powerset.len());
// DP state consists of:
// - The current minute
// - The current valve
// - The current set of open/closed valves
let mut dp = HashMap::new();
// 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...
// - Go to another neighbouring valve v', points: points[v', t-1, s]
// - If v not in s: Open current valve, points: points[v, t-1, s+{v}] + t
for minute in 1..=30 {
eprintln!("Minute {minute}");
for (valve_id, valve) in valves.iter().enumerate() {
for open in &powerset {
let mut score = valve
.next
.iter()
.map(|next_id| dp[&(minute - 1, *next_id, *open)])
.max()
.unwrap_or(0);
if valve.rate > 0 && !open.is_open(valve_id) {
let room_but_valve_open = dp[&(minute - 1, valve_id, open.open(valve_id))];
let pressure_until_end = (minute - 1) * valve.rate;
score = score.max(room_but_valve_open + pressure_until_end);
}
dp.insert((minute, valve_id, *open), score);
}
}
}
let part1 = dp[&(30, names["AA"], OpenSet::ALL_CLOSED)];
println!("Part 1: {part1}");
}

View file

@ -0,0 +1,10 @@
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II

View file

@ -0,0 +1,2 @@
Part 1: 1651
Part 2: ???