From ff8732bb80bfe6c8e588197b4bf7ab200f94d97d Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Fri, 16 Dec 2022 20:59:19 +0530 Subject: [PATCH] Added day 16 --- src/day16/1.rs | 106 ++++++++++++++++++++++++++++++++ src/day16/2.rs | 142 +++++++++++++++++++++++++++++++++++++++++++ src/day16/input.txt | 51 ++++++++++++++++ src/day16/sample.txt | 10 +++ 4 files changed, 309 insertions(+) create mode 100644 src/day16/input.txt create mode 100644 src/day16/sample.txt diff --git a/src/day16/1.rs b/src/day16/1.rs index e69de29..a6a2503 100644 --- a/src/day16/1.rs +++ b/src/day16/1.rs @@ -0,0 +1,106 @@ +#![feature(test)] + +use std::collections::HashMap; + +extern crate test; + +const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; + +#[derive(Clone, Debug, Ord, PartialEq, PartialOrd, Eq)] +struct Node { + flow: i32, + idx: usize, + leads_to: Vec, +} + +fn parse(input: &'static str) -> HashMap { + input + .lines() + .enumerate() + .map(|(i, line)| { + let mut num = 0; + let mut node = "".to_string(); + let mut children = vec![]; + for c in line.chars().skip(1).filter(|&c| { + ('A'..='Z').contains(&c) || ('0'..='9').contains(&c) || c == ',' || c == '=' + }) { + match c { + 'A'..='Z' => { + node.push(c); + } + '0'..='9' => num = num * 10 + (c as u8 - b'0') as i32, + '=' | ',' => { + children.push(node.clone()); + node.clear(); + } + _ => (), + } + } + + children.push(node); + + ( + children[0].clone(), + Node { + flow: num, + idx: i, + leads_to: children[1..].to_vec(), + }, + ) + }) + .collect() +} + +const MAX_TIME: i32 = 30; + +fn solution(input: HashMap) -> i32 { + let mut choices = HashMap::with_capacity(50); + choices.insert((0, "AA".to_string()), (0, 0, 0u128)); + + for minute in 0..MAX_TIME { + let mut new_choices = HashMap::with_capacity(50); + + for (k, choice) in choices { + let new_valve = &k.1; + let ip = input.get(new_valve).unwrap(); + let new_valve_idx = ip.idx; + + let new_time = choice.0 + 1; + let mut new_release = choice.1; + + for path in ip.leads_to.iter() { + let new_choice = (new_time, new_release, choice.2); + + new_choices.insert((new_release, path.to_string()), new_choice); + } + + if ip.flow > 0 && choice.2 & (1 << new_valve_idx) < 1 { + new_release += ip.flow * (MAX_TIME - minute - 1); + + let new_choice = (new_time, new_release, choice.2 | (1 << new_valve_idx)); + + new_choices.insert((new_release, new_valve.to_string()), new_choice); + } + } + + choices = new_choices; + } + + choices.values().map(|c| c.1).max().unwrap() +} + +fn main() { + for input in INPUTS.iter() { + let output = parse(input); + let score = solution(output); + println!("{}", score); + } +} +#[bench] +fn solution_bench(b: &mut test::Bencher) { + b.iter(|| { + let input = parse(INPUTS[1]); + let result = solution(input); + test::black_box(result); + }) +} diff --git a/src/day16/2.rs b/src/day16/2.rs index e69de29..23516f2 100644 --- a/src/day16/2.rs +++ b/src/day16/2.rs @@ -0,0 +1,142 @@ +#![feature(test)] + +use std::{cmp::Ordering, collections::HashMap}; +extern crate test; + +const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; + +#[derive(Clone, Debug, Ord, PartialEq, PartialOrd, Eq)] +struct Node { + flow: i32, + idx: usize, + leads_to: Vec, +} + +fn parse(input: &'static str) -> HashMap { + input + .lines() + .enumerate() + .map(|(i, line)| { + let mut num = 0; + let mut node = "".to_string(); + let mut children = vec![]; + for c in line.chars().skip(1).filter(|&c| { + ('A'..='Z').contains(&c) + || ('0'..='9').contains(&c) + || c == ',' + || c == ';' + || c == '=' + }) { + match c { + 'A'..='Z' => node.push(c), + '0'..='9' => num = num * 10 + (c as u8 - b'0') as i32, + '=' | ',' => { + children.push(node.clone()); + node.clear(); + } + + _ => (), + } + } + + children.push(node); + + ( + children[0].clone(), + Node { + flow: num, + idx: i, + leads_to: children[1..].to_vec(), + }, + ) + }) + .collect() +} + +const MAX_TIME: i32 = 26; + +fn solution(input: HashMap) -> i32 { + let mut new_choices = HashMap::with_capacity(500); + let mut choices = HashMap::with_capacity(500); + choices.insert((0, "AA".to_string(), "AA".to_string()), (0, 0u128)); + + 'outer: for minute in 0..MAX_TIME { + for (k, choice) in &choices { + let mut hpaths = input.get(&k.1).unwrap().leads_to.clone(); + hpaths.push(k.1.clone()); + + let mut epaths = input.get(&k.2).unwrap().leads_to.clone(); + epaths.push(k.2.clone()); + + if choice.1.count_ones() == input.len() as u32 { + break 'outer; + } + + for h in hpaths { + let epaths = epaths.clone(); + for e in epaths { + let new_h_valve = h.clone(); + let new_h_valve_flow = input.get(&new_h_valve).unwrap().flow; + let new_h_valve_idx = input.get(&new_h_valve).unwrap().idx; + + let mut new_release = choice.0; + let new_e_valve = e; + let new_e_valve_flow = input.get(&new_e_valve).unwrap().flow; + let new_e_valve_idx = input.get(&new_e_valve).unwrap().idx; + + let mut new_state = choice.1; + + match (new_e_valve.cmp(&k.2), new_h_valve.cmp(&k.1)) { + (Ordering::Equal, Ordering::Equal) => { + if (new_state & (1 << new_h_valve_idx) < 1) + && (new_state & (1 << new_e_valve_idx) < 1) + { + new_release += new_h_valve_flow * (MAX_TIME - minute - 1); + new_state |= 1 << new_h_valve_idx; + if new_state & (1 << new_e_valve_idx) < 1 { + new_release += new_e_valve_flow * (MAX_TIME - minute - 1); + new_state |= 1 << new_e_valve_idx; + } + } + } + (_, Ordering::Equal) if new_state & (1 << new_h_valve_idx) < 1 => { + new_release += new_h_valve_flow * (MAX_TIME - minute - 1); + new_state |= 1 << new_h_valve_idx; + } + (Ordering::Equal, _) if new_state & (1 << new_e_valve_idx) < 1 => { + new_release += new_e_valve_flow * (MAX_TIME - minute - 1); + new_state |= 1 << new_e_valve_idx; + } + + (_, _) => (), + } + + let new_choice = (new_release, new_state); + + new_choices.insert((new_release, new_h_valve, new_e_valve), new_choice); + } + } + } + + std::mem::swap(&mut choices, &mut new_choices); + new_choices.clear(); + } + + choices.values().map(|c| c.0).max().unwrap() +} + +fn main() { + for input in INPUTS.iter() { + let output = parse(input); + let score = solution(output); + println!("{}", score); + } +} +#[bench] +fn solution_bench(b: &mut test::Bencher) { + b.iter(|| { + let input = parse(INPUTS[1]); + let result = solution(input); + test::black_box(result); + }) +} diff --git a/src/day16/input.txt b/src/day16/input.txt new file mode 100644 index 0000000..e30487a --- /dev/null +++ b/src/day16/input.txt @@ -0,0 +1,51 @@ +Valve GS has flow rate=0; tunnels lead to valves KB, GW +Valve CB has flow rate=0; tunnels lead to valves GW, CT +Valve TP has flow rate=0; tunnels lead to valves LR, TH +Valve FI has flow rate=3; tunnels lead to valves DA, AY, ZO, MP, XP +Valve WV has flow rate=0; tunnels lead to valves TH, HG +Valve EA has flow rate=16; tunnels lead to valves PL, NG, AX +Valve AT has flow rate=9; tunnels lead to valves ZO, EM +Valve WS has flow rate=0; tunnels lead to valves GW, RD +Valve MP has flow rate=0; tunnels lead to valves AA, FI +Valve GE has flow rate=0; tunnels lead to valves AX, QN +Valve SA has flow rate=10; tunnels lead to valves NI, OM, RD, RC, GO +Valve NI has flow rate=0; tunnels lead to valves SA, YG +Valve GO has flow rate=0; tunnels lead to valves TH, SA +Valve IT has flow rate=0; tunnels lead to valves WB, KB +Valve NG has flow rate=0; tunnels lead to valves EA, KF +Valve RD has flow rate=0; tunnels lead to valves SA, WS +Valve LR has flow rate=12; tunnels lead to valves TP, XR +Valve TO has flow rate=22; tunnel leads to valve VW +Valve WF has flow rate=0; tunnels lead to valves XX, OO +Valve YD has flow rate=21; tunnel leads to valve NR +Valve XR has flow rate=0; tunnels lead to valves LR, KB +Valve KF has flow rate=0; tunnels lead to valves GW, NG +Valve OO has flow rate=0; tunnels lead to valves UD, WF +Valve HG has flow rate=0; tunnels lead to valves WV, YG +Valve CT has flow rate=0; tunnels lead to valves YG, CB +Valve DA has flow rate=0; tunnels lead to valves TH, FI +Valve YY has flow rate=0; tunnels lead to valves AA, YG +Valve VW has flow rate=0; tunnels lead to valves TO, EM +Valve RC has flow rate=0; tunnels lead to valves AA, SA +Valve PL has flow rate=0; tunnels lead to valves AA, EA +Valve TH has flow rate=14; tunnels lead to valves GO, WV, GJ, DA, TP +Valve QN has flow rate=24; tunnels lead to valves LC, GE +Valve XE has flow rate=0; tunnels lead to valves NA, XX +Valve XP has flow rate=0; tunnels lead to valves FI, OM +Valve AX has flow rate=0; tunnels lead to valves GE, EA +Valve EM has flow rate=0; tunnels lead to valves AT, VW +Valve NR has flow rate=0; tunnels lead to valves YD, PM +Valve YG has flow rate=4; tunnels lead to valves AY, HG, NI, YY, CT +Valve PM has flow rate=0; tunnels lead to valves UD, NR +Valve AY has flow rate=0; tunnels lead to valves YG, FI +Valve GJ has flow rate=0; tunnels lead to valves AA, TH +Valve LC has flow rate=0; tunnels lead to valves QN, GW +Valve UD has flow rate=17; tunnels lead to valves OO, PM +Valve AA has flow rate=0; tunnels lead to valves MP, GJ, YY, RC, PL +Valve OM has flow rate=0; tunnels lead to valves XP, SA +Valve WB has flow rate=0; tunnels lead to valves NA, IT +Valve GW has flow rate=11; tunnels lead to valves KF, GS, LC, CB, WS +Valve NA has flow rate=7; tunnels lead to valves WB, XE +Valve XX has flow rate=20; tunnels lead to valves XE, WF +Valve ZO has flow rate=0; tunnels lead to valves AT, FI +Valve KB has flow rate=8; tunnels lead to valves XR, GS, IT diff --git a/src/day16/sample.txt b/src/day16/sample.txt new file mode 100644 index 0000000..9f30acc --- /dev/null +++ b/src/day16/sample.txt @@ -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