From a794e2184046a8af78b23f9498f84b44c24540ea Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 16 Dec 2022 13:06:09 +0100 Subject: [PATCH] [rs] Solve 2022_16 part 1 --- inputs/2022/2022_16.input | 51 +++++++++++ inputs/2022/2022_16.solution | 2 + rs/src/main.rs | 1 + rs/src/y2022.rs | 1 + rs/src/y2022/d16.rs | 127 ++++++++++++++++++++++++++++ sample_inputs/2022/2022_16.input | 10 +++ sample_inputs/2022/2022_16.solution | 2 + 7 files changed, 194 insertions(+) create mode 100644 inputs/2022/2022_16.input create mode 100644 inputs/2022/2022_16.solution create mode 100644 rs/src/y2022/d16.rs create mode 100644 sample_inputs/2022/2022_16.input create mode 100644 sample_inputs/2022/2022_16.solution diff --git a/inputs/2022/2022_16.input b/inputs/2022/2022_16.input new file mode 100644 index 0000000..dc9b065 --- /dev/null +++ b/inputs/2022/2022_16.input @@ -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 diff --git a/inputs/2022/2022_16.solution b/inputs/2022/2022_16.solution new file mode 100644 index 0000000..905eda2 --- /dev/null +++ b/inputs/2022/2022_16.solution @@ -0,0 +1,2 @@ +Part 1: 1923 +Part 2: ??? diff --git a/rs/src/main.rs b/rs/src/main.rs index 86bbc61..70a62f7 100644 --- a/rs/src/main.rs +++ b/rs/src/main.rs @@ -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)] diff --git a/rs/src/y2022.rs b/rs/src/y2022.rs index 0871281..6c0c2a1 100644 --- a/rs/src/y2022.rs +++ b/rs/src/y2022.rs @@ -13,3 +13,4 @@ pub mod d12; pub mod d13; pub mod d14; pub mod d15; +pub mod d16; diff --git a/rs/src/y2022/d16.rs b/rs/src/y2022/d16.rs new file mode 100644 index 0000000..3380c40 --- /dev/null +++ b/rs/src/y2022/d16.rs @@ -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::>(); + (name, rate.parse().unwrap(), next) +} +#[derive(Debug)] +struct Valve { + rate: u32, + next: Vec, +} + +fn prepare_valves<'a>( + mut valves: Vec<(&'a str, u32, Vec<&str>)>, +) -> (HashMap<&'a str, usize>, Vec) { + // 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::>(); + + let valves = valves + .into_iter() + .map(|(_, rate, next)| { + let next = next.into_iter().map(|n| names[n]).collect(); + Valve { rate, next } + }) + .collect::>(); + + (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 { + 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::>() + } + + 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::>(); + + 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}"); +} diff --git a/sample_inputs/2022/2022_16.input b/sample_inputs/2022/2022_16.input new file mode 100644 index 0000000..9f30acc --- /dev/null +++ b/sample_inputs/2022/2022_16.input @@ -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 diff --git a/sample_inputs/2022/2022_16.solution b/sample_inputs/2022/2022_16.solution new file mode 100644 index 0000000..2d195b5 --- /dev/null +++ b/sample_inputs/2022/2022_16.solution @@ -0,0 +1,2 @@ +Part 1: 1651 +Part 2: ???