Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cmp::max;
- use std::collections::{BTreeSet, HashMap};
- use std::iter::zip;
- use std::ops::Index;
- use std::process::id;
- use itertools::Itertools;
- use pathfinding::prelude::{build_path, dijkstra, dijkstra_all};
- use rayon::iter::{IntoParallelRefIterator, ParallelBridge, ParallelIterator};
- use scan_fmt::scan_fmt;
- #[derive(Eq, PartialEq, Hash, Clone, Debug)]
- struct tunnel
- {
- valve_identifier: String,
- flow_rate: u16,
- tunnels: Vec<String>
- }
- //current idea have a hashmap of tunnels, hopefully outside the function that is always referenced to grab tunnel info.
- //each move costs LARGE_NUM - total_pressure_relieved
- #[derive(Eq, PartialEq, Hash, Clone, Debug)]
- struct tunnel2
- {
- valve_identifier: u8,
- flow_rate: u16,
- tunnels: Vec<u8>
- }
- #[derive(Eq, PartialEq, Hash, Clone, Debug)]
- struct Node
- {
- currentLoc: u8,
- valves_opened: BTreeSet<u8>,
- time:u8,
- //this calculates from the moment you close a valve
- totalPressureRelieved: u16,
- }
- fn genTunnelMap() -> (HashMap<String, u8>, HashMap<u8, tunnel2>) {
- let mut tunnelMap: HashMap<_, _> = Default::default();
- include_str!("../../input16").lines().for_each(|s| {
- let (s1, s2) = s.split_once(";").unwrap();
- let (valve_identifier, flow_rate) = scan_fmt!(s1, "Valve {} has flow rate={}", String, u16).unwrap();
- if s2.contains("tunnels")
- {
- let (_, list) = s2.split_at(24);
- let tunnels = list.split(", ").map(|s| s.to_string()).collect_vec();
- tunnelMap.insert(valve_identifier.to_owned(), tunnel { valve_identifier, flow_rate, tunnels });
- } else {
- //single tunnel case
- let (_, single) = s2.split_at(23);
- let tunnels = [single.to_string()].to_vec();
- tunnelMap.insert(valve_identifier.to_owned(), tunnel { valve_identifier, flow_rate, tunnels });
- }
- });
- let mut tempMap: HashMap<_, _> = Default::default();
- for (newIdentifier, (tunn_name, _)) in tunnelMap.iter().enumerate() {
- tempMap.insert(tunn_name.clone(), newIdentifier as u8);
- }
- let mut tunnelMap2: HashMap<_, _> = Default::default();
- for (_, tunn) in &tunnelMap {
- let newID = *tempMap.get(&tunn.valve_identifier).unwrap();
- let newLinkedTunns = tunn.tunnels.iter().map(|s| *tempMap.get(s).unwrap()).collect_vec();
- tunnelMap2.insert(newID, tunnel2 {
- valve_identifier: newID,
- flow_rate: tunn.flow_rate,
- tunnels: newLinkedTunns
- });
- }
- (tempMap, tunnelMap2)
- }
- pub fn day16_1(){
- let (tempMap, tunnelMap2) = genTunnelMap();
- //dbg!(&tunnelMap);
- const LARGE_NUM: u32 = 1000000;
- let res = dijkstra(&Node {
- currentLoc: *tempMap.get(&"AA".to_string()).unwrap(),
- valves_opened: Default::default(),
- time: 1,
- totalPressureRelieved: 0
- }, |x| {
- let mut moves = vec![];
- let next_time = x.time+1;
- let currTunnel = tunnelMap2.get(&x.currentLoc).unwrap();
- if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(&x.currentLoc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.insert(x.currentLoc);
- // we add the opening valve move here
- let deltaPressure = ((30 - x.time as u16) * currTunnel.flow_rate);
- moves.push((Node {
- currentLoc: x.currentLoc,
- valves_opened: newValveOpenedList,
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- for tun in &currTunnel.tunnels
- {
- //we add each move option here
- moves.push((Node {
- currentLoc: *tun,
- valves_opened: x.valves_opened.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved
- }, LARGE_NUM ));
- }
- moves
- }, |x|
- {
- // you are able to set this to 29 since the last minute you cant do anything that helps you
- x.time == 29
- }
- ).unwrap();
- println!("{}", res.0.last().unwrap().totalPressureRelieved);
- }
- pub fn day16_2()
- {
- let (tempMap, tunnelMap2) = genTunnelMap();
- const LARGE_NUM: u32 = 1000000;
- let allPaths = dijkstra_all(&Node {
- currentLoc: *tempMap.get(&"AA".to_string()).unwrap(),
- valves_opened: Default::default(),
- time: 1,
- totalPressureRelieved: 0
- }, |x| {
- let mut moves = vec![];
- if x.time == 25
- {
- // we don't allow any moves after 26 steps
- //you are able to set this to 25 since the last minute you cant do anything that helps you
- return moves;
- }
- let next_time = x.time+1;
- let currTunnel = tunnelMap2.get(&x.currentLoc).unwrap();
- if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(&x.currentLoc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.insert(x.currentLoc);
- // we add the opening valve move here
- let deltaPressure = ((26 - x.time as u16) * currTunnel.flow_rate);
- moves.push((Node {
- currentLoc: x.currentLoc,
- valves_opened: newValveOpenedList,
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- for tun in &currTunnel.tunnels
- {
- //we add each move option here
- moves.push((Node {
- currentLoc: *tun,
- valves_opened: x.valves_opened.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved
- }, LARGE_NUM ));
- }
- moves
- }
- );
- let mut valveSetToPressureMap: HashMap<_, _> = Default::default();
- allPaths.iter().for_each(|(node, _ )|{
- if (node.time != 25) || (node.totalPressureRelieved == 0) //|| (node.valves_opened.len() < 3)
- {
- return;
- }
- if !valveSetToPressureMap.contains_key(&node.valves_opened) || *valveSetToPressureMap.index(&node.valves_opened) < node.totalPressureRelieved
- {
- valveSetToPressureMap.insert(&node.valves_opened, node.totalPressureRelieved);
- }
- });
- let ans: u16 = valveSetToPressureMap.iter().cartesian_product(&valveSetToPressureMap).map(|x| {
- if x.0.0.is_disjoint(x.1.0) {
- x.0.1 + x.1.1
- }
- else {
- 0
- }
- }).max().unwrap();
- println!("{}", ans);
- }
- #[derive(Eq, PartialEq, Hash, Clone, Debug)]
- struct Node2
- {
- currentLocs: BTreeSet<u8>,
- valves_opened: BTreeSet<u8>,
- time:u8,
- //this calculates from the moment you close a valve
- totalPressureRelieved: u16,
- }
- pub fn day16_2_too_much_memory(){
- let (tempMap, tunnelMap2) = genTunnelMap();
- const LARGE_NUM: u32 = 1000000;
- let res = dijkstra(&Node2 {
- currentLocs: BTreeSet::from([*tempMap.get(&"AA".to_string()).unwrap()]),
- valves_opened: Default::default(),
- time: 1,
- totalPressureRelieved: 0
- }, |x| {
- let mut moves = vec![];
- let next_time = x.time+1;
- //case where elephant and I am in different tunnels
- if x.currentLocs.len() == 2 {
- let firstLoc = x.currentLocs.first().unwrap();
- let secondLoc = x.currentLocs.last().unwrap();
- let currTunnel1 = tunnelMap2.get(firstLoc).unwrap();
- let currTunnel2 = tunnelMap2.get(secondLoc).unwrap();
- //case where we both open valves
- if (currTunnel1.flow_rate != 0) && (!x.valves_opened.contains(firstLoc)) &&
- (currTunnel2.flow_rate != 0) && (!x.valves_opened.contains(secondLoc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.extend([firstLoc, secondLoc]);
- // we add the opening valve move here
- let deltaPressure = ((26 - x.time as u16) * currTunnel1.flow_rate) + ((26 - x.time as u16) * currTunnel2.flow_rate);
- moves.push((Node2 {
- currentLocs: x.currentLocs.clone(),
- valves_opened: newValveOpenedList,
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- //case where we open only first valve
- if (currTunnel1.flow_rate != 0) && (!x.valves_opened.contains(firstLoc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.insert(*firstLoc);
- let deltaPressure = ((26 - x.time as u16) * currTunnel1.flow_rate);
- for tun in &currTunnel2.tunnels
- {
- moves.push((Node2 {
- currentLocs: BTreeSet::from([*firstLoc, *tun]),
- valves_opened: newValveOpenedList.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- }
- //case where we open only second valve
- if (currTunnel2.flow_rate != 0) && (!x.valves_opened.contains(secondLoc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.insert(*secondLoc);
- let deltaPressure = ((26 - x.time as u16) * currTunnel2.flow_rate);
- for tun in &currTunnel1.tunnels
- {
- moves.push((Node2 {
- currentLocs: BTreeSet::from([*secondLoc, *tun]),
- valves_opened: newValveOpenedList.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- }
- // case where we both move
- for (newtun1, newtun2) in currTunnel1.tunnels.iter().cartesian_product(&currTunnel2.tunnels) {
- moves.push((Node2 {
- currentLocs: BTreeSet::from([*newtun1, *newtun2]),
- valves_opened: x.valves_opened.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved
- }, LARGE_NUM));
- }
- }
- //case where we are both in the same place
- else if x.currentLocs.len() == 1
- {
- let loc = x.currentLocs.first().unwrap();
- let currTunnel = tunnelMap2.get(loc).unwrap();
- //case where one of us opens the valve
- if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(loc))
- {
- let mut newValveOpenedList = x.valves_opened.clone();
- newValveOpenedList.insert(*loc);
- let deltaPressure = ((26 - x.time as u16) * currTunnel.flow_rate);
- for tun in &currTunnel.tunnels
- {
- moves.push((Node2 {
- currentLocs: BTreeSet::from([*loc, *tun]),
- valves_opened: newValveOpenedList.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved + deltaPressure
- }, LARGE_NUM - deltaPressure as u32));
- }
- }
- //case where we both move
- for (newtun1, newtun2) in currTunnel.tunnels.iter().cartesian_product(&currTunnel.tunnels) {
- moves.push((Node2 {
- currentLocs: BTreeSet::from([*newtun1, *newtun2]),
- valves_opened: x.valves_opened.clone(),
- time: next_time,
- totalPressureRelieved: x.totalPressureRelieved
- }, LARGE_NUM));
- }
- }
- moves
- }, |x|
- {
- // you are able to set this to 25 since the last minute you or the elephant cant do anything that helps you
- x.time == 26
- }
- ).unwrap();
- println!("{:?}", res.0);
- println!("{}", res.0.last().unwrap().totalPressureRelieved);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement