adventofcode

git clone https://git.ce9e.org/adventofcode.git

commit
04348834a32d318307642ed814c794f007ecd8b5
parent
150ed5b49297d8847c67da395af813b348ce750d
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2022-12-16 10:43
2022-12-16 part 1

Diffstat

A 2022/16/input.txt 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2022/16/solution.rs 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2022/16/test.txt 10 ++++++++++

3 files changed, 211 insertions, 0 deletions


diff --git a/2022/16/input.txt b/2022/16/input.txt

@@ -0,0 +1,57 @@
   -1     1 Valve TM has flow rate=3; tunnels lead to valves WB, PE, DX, TK, CH
   -1     2 Valve ST has flow rate=21; tunnels lead to valves NS, DE, UX, XU
   -1     3 Valve IX has flow rate=0; tunnels lead to valves DK, LR
   -1     4 Valve OG has flow rate=0; tunnels lead to valves MN, FK
   -1     5 Valve FR has flow rate=0; tunnels lead to valves JQ, GS
   -1     6 Valve HU has flow rate=0; tunnels lead to valves TJ, XX
   -1     7 Valve WC has flow rate=15; tunnel leads to valve TJ
   -1     8 Valve JT has flow rate=0; tunnels lead to valves OV, AA
   -1     9 Valve DW has flow rate=0; tunnels lead to valves FK, AA
   -1    10 Valve RG has flow rate=0; tunnels lead to valves PS, DK
   -1    11 Valve JQ has flow rate=14; tunnels lead to valves VM, FR
   -1    12 Valve XX has flow rate=5; tunnels lead to valves GP, MN, WB, LM, HU
   -1    13 Valve IN has flow rate=11; tunnels lead to valves OK, GS, DU
   -1    14 Valve LR has flow rate=7; tunnels lead to valves IX, NR, YY, HZ, PR
   -1    15 Valve TK has flow rate=0; tunnels lead to valves TM, OV
   -1    16 Valve VM has flow rate=0; tunnels lead to valves KQ, JQ
   -1    17 Valve IC has flow rate=0; tunnels lead to valves FK, DU
   -1    18 Valve CH has flow rate=0; tunnels lead to valves EZ, TM
   -1    19 Valve OV has flow rate=10; tunnels lead to valves YW, JT, NN, TK
   -1    20 Valve KQ has flow rate=17; tunnels lead to valves VM, YW, CY
   -1    21 Valve NR has flow rate=0; tunnels lead to valves FK, LR
   -1    22 Valve MN has flow rate=0; tunnels lead to valves OG, XX
   -1    23 Valve YY has flow rate=0; tunnels lead to valves LR, LM
   -1    24 Valve OK has flow rate=0; tunnels lead to valves CY, IN
   -1    25 Valve DK has flow rate=20; tunnels lead to valves FA, RG, IX
   -1    26 Valve CY has flow rate=0; tunnels lead to valves KQ, OK
   -1    27 Valve PR has flow rate=0; tunnels lead to valves DX, LR
   -1    28 Valve DE has flow rate=0; tunnels lead to valves ST, EL
   -1    29 Valve TJ has flow rate=0; tunnels lead to valves WC, HU
   -1    30 Valve NS has flow rate=0; tunnels lead to valves WU, ST
   -1    31 Valve PE has flow rate=0; tunnels lead to valves TM, XO
   -1    32 Valve DU has flow rate=0; tunnels lead to valves IN, IC
   -1    33 Valve DX has flow rate=0; tunnels lead to valves TM, PR
   -1    34 Valve EQ has flow rate=0; tunnels lead to valves AA, GP
   -1    35 Valve AA has flow rate=0; tunnels lead to valves JT, EZ, HZ, DW, EQ
   -1    36 Valve WB has flow rate=0; tunnels lead to valves TM, XX
   -1    37 Valve PF has flow rate=23; tunnels lead to valves BP, WU
   -1    38 Valve FJ has flow rate=19; tunnels lead to valves DO, TY, NN, PS
   -1    39 Valve GP has flow rate=0; tunnels lead to valves XX, EQ
   -1    40 Valve FK has flow rate=4; tunnels lead to valves DW, XO, OG, IC, NR
   -1    41 Valve DO has flow rate=0; tunnels lead to valves XU, FJ
   -1    42 Valve XO has flow rate=0; tunnels lead to valves FK, PE
   -1    43 Valve PS has flow rate=0; tunnels lead to valves RG, FJ
   -1    44 Valve MD has flow rate=25; tunnel leads to valve BP
   -1    45 Valve EZ has flow rate=0; tunnels lead to valves CH, AA
   -1    46 Valve GS has flow rate=0; tunnels lead to valves IN, FR
   -1    47 Valve XU has flow rate=0; tunnels lead to valves DO, ST
   -1    48 Valve WU has flow rate=0; tunnels lead to valves PF, NS
   -1    49 Valve YW has flow rate=0; tunnels lead to valves OV, KQ
   -1    50 Valve HZ has flow rate=0; tunnels lead to valves LR, AA
   -1    51 Valve TY has flow rate=0; tunnels lead to valves FJ, EL
   -1    52 Valve BP has flow rate=0; tunnels lead to valves MD, PF
   -1    53 Valve EL has flow rate=18; tunnels lead to valves DE, TY
   -1    54 Valve UX has flow rate=0; tunnels lead to valves FA, ST
   -1    55 Valve FA has flow rate=0; tunnels lead to valves UX, DK
   -1    56 Valve NN has flow rate=0; tunnels lead to valves OV, FJ
   -1    57 Valve LM has flow rate=0; tunnels lead to valves XX, YY

diff --git a/2022/16/solution.rs b/2022/16/solution.rs

@@ -0,0 +1,144 @@
   -1     1 use std::collections::HashMap;
   -1     2 use std::collections::HashSet;
   -1     3 
   -1     4 #[path = "../lib.rs"] mod lib;
   -1     5 
   -1     6 #[derive(Clone)]
   -1     7 struct Valve {
   -1     8     rate: u64,
   -1     9     tunnels: HashMap<String, u64>,
   -1    10 }
   -1    11 
   -1    12 struct QueueEntry {
   -1    13     pos: String,
   -1    14     open: HashSet<String>,
   -1    15     time: u64,
   -1    16     pressure: u64,
   -1    17     potential: u64,
   -1    18 }
   -1    19 
   -1    20 fn get_input() -> HashMap<String, Valve> {
   -1    21     let mut map = HashMap::new();
   -1    22 
   -1    23     for line in lib::iter_input() {
   -1    24         let (line1, line2) = lib::split_once(line.as_str(), ';').unwrap();
   -1    25         let (line11, line12) = lib::split_once(line1, '=').unwrap();
   -1    26         let name = line11[6..8].to_string();
   -1    27         let tunnels_s = match line2.strip_prefix(" tunnels lead to valves ") {
   -1    28             Some(s) => s,
   -1    29             _ => line2.strip_prefix(" tunnel leads to valve ").unwrap(),
   -1    30         };
   -1    31         let mut tunnels = HashMap::new();
   -1    32         for s in tunnels_s.split(", ") {
   -1    33             tunnels.insert(s.to_string(), 1);
   -1    34         }
   -1    35         map.insert(name, Valve {
   -1    36             rate: line12.parse().unwrap(),
   -1    37             tunnels: tunnels,
   -1    38         });
   -1    39     }
   -1    40 
   -1    41     return map;
   -1    42 }
   -1    43 
   -1    44 fn make_entry(valves: &HashMap<String, Valve>, pos: String, open: HashSet<String>, time: u64, pressure: u64) -> QueueEntry {
   -1    45     let mut rates = valves.iter()
   -1    46         .filter(|(key, _valve)| !open.contains(*key))
   -1    47         .map(|(_key, valve)| valve.rate)
   -1    48         .collect::<Vec<u64>>();
   -1    49     rates.sort();
   -1    50     rates.reverse();
   -1    51 
   -1    52     let mut potential = pressure;
   -1    53     let mut i = 0;
   -1    54     let mut t = time;
   -1    55     while i < rates.len() && t > 1 {
   -1    56         potential += rates[i] * (t - 1);
   -1    57         i += 1;
   -1    58         t -= 2;
   -1    59     }
   -1    60 
   -1    61     return QueueEntry { pos, open, time, pressure, potential };
   -1    62 }
   -1    63 
   -1    64 fn get_next(queue: &mut Vec<QueueEntry>) -> Option<QueueEntry> {
   -1    65     // let (i, _) = queue.iter()
   -1    66     //     .enumerate()
   -1    67     //     .max_by_key(|(_, entry)| entry.pressure)?;
   -1    68     // return Some(queue.remove(i));
   -1    69     return queue.pop();
   -1    70 }
   -1    71 
   -1    72 fn part1(valves: &HashMap<String, Valve>) -> u64 {
   -1    73     let mut max_pressure = 0;
   -1    74     let mut queue = vec![make_entry(valves, "AA".to_string(), HashSet::new(), 30, 0)];
   -1    75 
   -1    76     while let Some(entry) = get_next(&mut queue) {
   -1    77         // PERF: stop early if there is no way to reach max_pressure
   -1    78         if entry.potential <= max_pressure {
   -1    79             continue;
   -1    80         }
   -1    81 
   -1    82         println!("{} {} {} {} {} {}", entry.pos, entry.time, entry.pressure, entry.potential, max_pressure, queue.len());
   -1    83 
   -1    84         if !entry.open.contains(&entry.pos) && valves[&entry.pos].rate > 0 {
   -1    85             let pressure = entry.pressure + valves[&entry.pos].rate * (entry.time - 1);
   -1    86             if pressure > max_pressure {
   -1    87                 max_pressure = pressure;
   -1    88             }
   -1    89 
   -1    90             let mut open = entry.open.clone();
   -1    91             open.insert(entry.pos.clone());
   -1    92             queue.push(make_entry(valves, entry.pos.clone(), open, entry.time - 1, pressure));
   -1    93         }
   -1    94 
   -1    95         for (name, len) in valves[&entry.pos].tunnels.iter() {
   -1    96             if entry.time >= *len {
   -1    97                 queue.push(make_entry(valves, name.clone(), entry.open.clone(), entry.time - len, entry.pressure));
   -1    98             }
   -1    99         }
   -1   100     }
   -1   101 
   -1   102     return max_pressure;
   -1   103 }
   -1   104 
   -1   105 fn optimize_tunnels(valves: &HashMap<String, Valve>, name: &String, path: &Vec<String>) -> HashMap<String, u64> {
   -1   106     let mut tunnels = HashMap::new();
   -1   107     let mut p = path.clone();
   -1   108     p.push(name.clone());
   -1   109 
   -1   110     for (tunnel_name, d) in valves[name].tunnels.iter() {
   -1   111         if valves[tunnel_name].rate > 0 || tunnel_name == "AA" {
   -1   112             if *tunnels.get(tunnel_name).unwrap_or(&u64::MAX) > *d {
   -1   113                 tunnels.insert(tunnel_name.clone(), *d);
   -1   114             }
   -1   115         } else if !p.contains(tunnel_name) {
   -1   116             for (tunnel_name2, d2) in optimize_tunnels(valves, tunnel_name, &p).iter() {
   -1   117                 if !p.contains(tunnel_name2) {
   -1   118                     if *tunnels.get(tunnel_name2).unwrap_or(&u64::MAX) > *d + *d2 {
   -1   119                         tunnels.insert(tunnel_name2.clone(), *d + *d2);
   -1   120                     }
   -1   121                 }
   -1   122             }
   -1   123         }
   -1   124     }
   -1   125 
   -1   126     return tunnels;
   -1   127 }
   -1   128 
   -1   129 fn main() {
   -1   130     let valves = get_input();
   -1   131 
   -1   132     let mut optimized = HashMap::new();
   -1   133     for (name, valve) in valves.iter() {
   -1   134         if valve.rate > 0 || name == "AA" {
   -1   135             optimized.insert(name.clone(), Valve {
   -1   136                 rate: valve.rate,
   -1   137                 tunnels: optimize_tunnels(&valves, name, &vec![]),
   -1   138             });
   -1   139         }
   -1   140     }
   -1   141 
   -1   142     println!("part1: {}", part1(&optimized));
   -1   143     println!("part2: {}", 0);
   -1   144 }

diff --git a/2022/16/test.txt b/2022/16/test.txt

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