2022 - Day 16
This commit is contained in:
parent
c43808fbfc
commit
c5a0ad16a1
61
2022/input/16/input
Normal file
61
2022/input/16/input
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
Valve KR has flow rate=17; tunnels lead to valves WA, JQ, JY, KI
|
||||||
|
Valve JN has flow rate=0; tunnels lead to valves XS, JQ
|
||||||
|
Valve JY has flow rate=0; tunnels lead to valves KR, AP
|
||||||
|
Valve WE has flow rate=0; tunnels lead to valves GY, XS
|
||||||
|
Valve HW has flow rate=0; tunnels lead to valves GP, AA
|
||||||
|
Valve QS has flow rate=0; tunnels lead to valves WW, MF
|
||||||
|
Valve MF has flow rate=15; tunnels lead to valves RJ, QS
|
||||||
|
Valve IM has flow rate=0; tunnels lead to valves WH, HS
|
||||||
|
Valve RJ has flow rate=0; tunnels lead to valves MF, PM
|
||||||
|
Valve IG has flow rate=0; tunnels lead to valves WX, ZY
|
||||||
|
Valve YL has flow rate=0; tunnels lead to valves GY, EB
|
||||||
|
Valve LI has flow rate=25; tunnels lead to valves YS, SI
|
||||||
|
Valve WW has flow rate=6; tunnels lead to valves PJ, QS
|
||||||
|
Valve QK has flow rate=0; tunnels lead to valves MV, AU
|
||||||
|
Valve AU has flow rate=20; tunnels lead to valves QK, BT, VK
|
||||||
|
Valve WH has flow rate=0; tunnels lead to valves MV, IM
|
||||||
|
Valve YS has flow rate=0; tunnels lead to valves ZL, LI
|
||||||
|
Valve FR has flow rate=0; tunnels lead to valves XS, AA
|
||||||
|
Valve NX has flow rate=0; tunnels lead to valves KI, NG
|
||||||
|
Valve OI has flow rate=5; tunnels lead to valves SU, OX, LW, JH, DK
|
||||||
|
Valve YJ has flow rate=0; tunnels lead to valves XK, XU
|
||||||
|
Valve DK has flow rate=0; tunnels lead to valves OI, IZ
|
||||||
|
Valve SU has flow rate=0; tunnels lead to valves OI, XU
|
||||||
|
Valve OH has flow rate=0; tunnels lead to valves CX, WX
|
||||||
|
Valve HS has flow rate=8; tunnels lead to valves UY, IM, WJ, XK, UC
|
||||||
|
Valve UY has flow rate=0; tunnels lead to valves HS, OX
|
||||||
|
Valve AP has flow rate=0; tunnels lead to valves JY, GY
|
||||||
|
Valve JQ has flow rate=0; tunnels lead to valves KR, JN
|
||||||
|
Valve XK has flow rate=0; tunnels lead to valves YJ, HS
|
||||||
|
Valve PM has flow rate=0; tunnels lead to valves RJ, ZY
|
||||||
|
Valve WJ has flow rate=0; tunnels lead to valves AA, HS
|
||||||
|
Valve VK has flow rate=0; tunnels lead to valves AU, SI
|
||||||
|
Valve OX has flow rate=0; tunnels lead to valves UY, OI
|
||||||
|
Valve ZL has flow rate=0; tunnels lead to valves YS, MV
|
||||||
|
Valve LW has flow rate=0; tunnels lead to valves TT, OI
|
||||||
|
Valve TT has flow rate=0; tunnels lead to valves LW, MV
|
||||||
|
Valve PJ has flow rate=0; tunnels lead to valves UC, WW
|
||||||
|
Valve UC has flow rate=0; tunnels lead to valves PJ, HS
|
||||||
|
Valve XU has flow rate=3; tunnels lead to valves EB, CW, SU, TL, YJ
|
||||||
|
Valve XS has flow rate=4; tunnels lead to valves IZ, CW, WE, JN, FR
|
||||||
|
Valve CW has flow rate=0; tunnels lead to valves XU, XS
|
||||||
|
Valve TF has flow rate=0; tunnels lead to valves AA, TL
|
||||||
|
Valve EB has flow rate=0; tunnels lead to valves XU, YL
|
||||||
|
Valve WA has flow rate=0; tunnels lead to valves KR, BT
|
||||||
|
Valve GY has flow rate=9; tunnels lead to valves GP, AP, YL, ZO, WE
|
||||||
|
Valve IZ has flow rate=0; tunnels lead to valves DK, XS
|
||||||
|
Valve KI has flow rate=0; tunnels lead to valves NX, KR
|
||||||
|
Valve AA has flow rate=0; tunnels lead to valves HW, TF, FR, JH, WJ
|
||||||
|
Valve ZO has flow rate=0; tunnels lead to valves GY, QM
|
||||||
|
Valve QM has flow rate=0; tunnels lead to valves ZO, CX
|
||||||
|
Valve SI has flow rate=0; tunnels lead to valves LI, VK
|
||||||
|
Valve BT has flow rate=0; tunnels lead to valves AU, WA
|
||||||
|
Valve BC has flow rate=0; tunnels lead to valves CX, ZY
|
||||||
|
Valve NG has flow rate=21; tunnel leads to valve NX
|
||||||
|
Valve WX has flow rate=16; tunnels lead to valves IG, OH
|
||||||
|
Valve GP has flow rate=0; tunnels lead to valves HW, GY
|
||||||
|
Valve JH has flow rate=0; tunnels lead to valves AA, OI
|
||||||
|
Valve CX has flow rate=13; tunnels lead to valves OH, BC, QM
|
||||||
|
Valve TL has flow rate=0; tunnels lead to valves TF, XU
|
||||||
|
Valve MV has flow rate=14; tunnels lead to valves QK, ZL, WH, TT
|
||||||
|
Valve ZY has flow rate=10; tunnels lead to valves PM, BC, IG
|
10
2022/input/16/test-1
Normal file
10
2022/input/16/test-1
Normal 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
|
180
2022/src/bin/day16.rs
Normal file
180
2022/src/bin/day16.rs
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
#![feature(test)]
|
||||||
|
use std::{collections::{HashMap, VecDeque, HashSet}, str::FromStr};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use aoc::Solver;
|
||||||
|
|
||||||
|
// -- Runners --
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
Day::solve()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_test1() -> Result<()> {
|
||||||
|
Day::test(Day::part1, "test-1", 1651)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part1_solution() -> Result<()> {
|
||||||
|
Day::test(Day::part1, "input", 1647)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part2_test1() -> Result<()> {
|
||||||
|
Day::test(Day::part2, "test-1", 1707)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part2_solution() -> Result<()> {
|
||||||
|
Day::test(Day::part2, "input", 2169)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmarks
|
||||||
|
extern crate test;
|
||||||
|
#[bench]
|
||||||
|
#[ignore]
|
||||||
|
fn part1_bench(b: &mut test::Bencher) {
|
||||||
|
Day::benchmark(Day::part1, b)
|
||||||
|
}
|
||||||
|
#[bench]
|
||||||
|
#[ignore]
|
||||||
|
fn part2_bench(b: &mut test::Bencher) {
|
||||||
|
Day::benchmark(Day::part2, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Valve {
|
||||||
|
flowrate: i32,
|
||||||
|
connections: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Volcano {
|
||||||
|
valves: HashMap<String, Valve>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Volcano {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
|
let valves = input
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
let mut iter = line.splitn(10, " ");
|
||||||
|
|
||||||
|
let name = iter.nth(1).unwrap().into();
|
||||||
|
let flowrate = iter.nth(2).unwrap().chars().filter(|c| c.is_digit(10)).collect::<String>().parse().unwrap();
|
||||||
|
|
||||||
|
let connections = iter.nth(4).unwrap().split(", ").map(|name| name.into()).collect();
|
||||||
|
|
||||||
|
(name, Valve {flowrate, connections})
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
Ok(Volcano { valves })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
|
struct State {
|
||||||
|
name: String,
|
||||||
|
time: i32,
|
||||||
|
opened: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_best(root: String, volcano: &Volcano, opened: Vec<String>, time: i32) -> (i32, Vec<String>) {
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back((State{name: root, time, opened}, 0));
|
||||||
|
|
||||||
|
let mut best = 0;
|
||||||
|
let mut best_opened = Vec::new();
|
||||||
|
let mut evaluated = HashSet::new();
|
||||||
|
loop {
|
||||||
|
// We are done now
|
||||||
|
if queue.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = queue.pop_front().unwrap();
|
||||||
|
|
||||||
|
// Check if we have run out of time
|
||||||
|
if state.0.time <= 1 {
|
||||||
|
if state.1 > best {
|
||||||
|
best = state.1;
|
||||||
|
best_opened = state.0.opened;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if evaluated.contains(&state.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_valve = volcano.valves.get(&state.0.name).unwrap();
|
||||||
|
|
||||||
|
// Two options:
|
||||||
|
// 1: Open valve [Only if current valve is not opened and has a
|
||||||
|
// non-zero flowrate]
|
||||||
|
// 2: Move to other valve
|
||||||
|
|
||||||
|
// Option 1
|
||||||
|
if !state.0.opened.contains(&state.0.name) && current_valve.flowrate != 0 {
|
||||||
|
// Add the current valve to the list of opened valves
|
||||||
|
state.0.opened.push(state.0.name.clone());
|
||||||
|
|
||||||
|
let new_value = state.1 + (state.0.time-1) * current_valve.flowrate;
|
||||||
|
let ns = (State {name: state.0.name.to_owned(), time: state.0.time-1, opened: state.0.opened.clone()}, new_value);
|
||||||
|
queue.push_back(ns);
|
||||||
|
|
||||||
|
state.0.opened.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option 2
|
||||||
|
for connection in current_valve.connections.iter() {
|
||||||
|
let ns = (State {name: connection.to_owned(), time: state.0.time-1, opened: state.0.opened.clone()}, state.1);
|
||||||
|
queue.push_back(ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluated.insert(State{name: state.0.name.to_owned(), time: state.0.time, opened: state.0.opened.clone()});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (best, best_opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Solution --
|
||||||
|
pub struct Day;
|
||||||
|
impl aoc::Solver for Day {
|
||||||
|
type Output1 = i32;
|
||||||
|
type Output2 = i32;
|
||||||
|
|
||||||
|
fn day() -> u8 {
|
||||||
|
16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Self::Output1 {
|
||||||
|
let volcano = Volcano::from_str(input).unwrap();
|
||||||
|
|
||||||
|
find_best("AA".to_owned(), &volcano, Vec::new(), 30).0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> Self::Output2 {
|
||||||
|
let volcano = Volcano::from_str(input).unwrap();
|
||||||
|
|
||||||
|
let time = 26;
|
||||||
|
|
||||||
|
|
||||||
|
// This solution is very much a hack
|
||||||
|
// In the 26 minutes we can not turn on all the valves
|
||||||
|
// So the player tries to go for the best possible solution before running out of time
|
||||||
|
// The elephant will then look at the remaining valves and find the best remaing solution
|
||||||
|
// Problem with this solution is that it assumes we run out of time before opening all
|
||||||
|
// non-zero valves
|
||||||
|
// However this is not the case in the example, so it will actually fail the example
|
||||||
|
// @TODO Implement a proper solution that can also solve the example
|
||||||
|
let player = find_best("AA".to_owned(), &volcano, Vec::new(), time);
|
||||||
|
let elephant = find_best("AA".to_owned(), &volcano, player.1, time);
|
||||||
|
|
||||||
|
player.0 + elephant.0
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user