Advertisement
Guest User

day16

a guest
Dec 22nd, 2022
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 12.54 KB | None | 0 0
  1. use std::cmp::max;
  2. use std::collections::{BTreeSet, HashMap};
  3. use std::iter::zip;
  4. use std::ops::Index;
  5. use std::process::id;
  6. use itertools::Itertools;
  7. use pathfinding::prelude::{build_path, dijkstra, dijkstra_all};
  8. use rayon::iter::{IntoParallelRefIterator, ParallelBridge, ParallelIterator};
  9. use scan_fmt::scan_fmt;
  10.  
  11. #[derive(Eq, PartialEq, Hash, Clone, Debug)]
  12. struct tunnel
  13. {
  14.     valve_identifier: String,
  15.     flow_rate: u16,
  16.     tunnels: Vec<String>
  17. }
  18.  
  19. //current idea have a hashmap of tunnels, hopefully outside the function that is always referenced to grab tunnel info.
  20. //each move costs LARGE_NUM - total_pressure_relieved
  21.  
  22.  
  23. #[derive(Eq, PartialEq, Hash, Clone, Debug)]
  24. struct tunnel2
  25. {
  26.     valve_identifier: u8,
  27.     flow_rate: u16,
  28.     tunnels: Vec<u8>
  29. }
  30.  
  31. #[derive(Eq, PartialEq, Hash, Clone, Debug)]
  32. struct Node
  33. {
  34.     currentLoc: u8,
  35.     valves_opened: BTreeSet<u8>,
  36.     time:u8,
  37.     //this calculates from the moment you close a valve
  38.     totalPressureRelieved: u16,
  39. }
  40.  
  41. fn genTunnelMap() -> (HashMap<String, u8>, HashMap<u8, tunnel2>) {
  42.     let mut tunnelMap: HashMap<_, _> = Default::default();
  43.     include_str!("../../input16").lines().for_each(|s| {
  44.         let (s1, s2) = s.split_once(";").unwrap();
  45.         let (valve_identifier, flow_rate) = scan_fmt!(s1, "Valve {} has flow rate={}", String, u16).unwrap();
  46.         if s2.contains("tunnels")
  47.         {
  48.             let (_, list) = s2.split_at(24);
  49.             let tunnels = list.split(", ").map(|s| s.to_string()).collect_vec();
  50.             tunnelMap.insert(valve_identifier.to_owned(), tunnel { valve_identifier, flow_rate, tunnels });
  51.         } else {
  52.             //single tunnel case
  53.             let (_, single) = s2.split_at(23);
  54.             let tunnels = [single.to_string()].to_vec();
  55.             tunnelMap.insert(valve_identifier.to_owned(), tunnel { valve_identifier, flow_rate, tunnels });
  56.         }
  57.     });
  58.     let mut tempMap: HashMap<_, _> = Default::default();
  59.     for (newIdentifier, (tunn_name, _)) in tunnelMap.iter().enumerate() {
  60.         tempMap.insert(tunn_name.clone(), newIdentifier as u8);
  61.     }
  62.     let mut tunnelMap2: HashMap<_, _> = Default::default();
  63.     for (_, tunn) in &tunnelMap {
  64.         let newID = *tempMap.get(&tunn.valve_identifier).unwrap();
  65.         let newLinkedTunns = tunn.tunnels.iter().map(|s| *tempMap.get(s).unwrap()).collect_vec();
  66.         tunnelMap2.insert(newID, tunnel2 {
  67.             valve_identifier: newID,
  68.             flow_rate: tunn.flow_rate,
  69.             tunnels: newLinkedTunns
  70.         });
  71.     }
  72.     (tempMap, tunnelMap2)
  73. }
  74.  
  75. pub fn day16_1(){
  76.     let (tempMap, tunnelMap2) = genTunnelMap();
  77.     //dbg!(&tunnelMap);
  78.     const LARGE_NUM: u32 = 1000000;
  79.     let res = dijkstra(&Node {
  80.         currentLoc: *tempMap.get(&"AA".to_string()).unwrap(),
  81.         valves_opened: Default::default(),
  82.         time: 1,
  83.         totalPressureRelieved: 0
  84.     }, |x| {
  85.         let mut moves = vec![];
  86.         let next_time = x.time+1;
  87.         let currTunnel = tunnelMap2.get(&x.currentLoc).unwrap();
  88.         if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(&x.currentLoc))
  89.         {
  90.             let mut newValveOpenedList = x.valves_opened.clone();
  91.             newValveOpenedList.insert(x.currentLoc);
  92.             // we add the opening valve move here
  93.             let deltaPressure = ((30 - x.time as u16) * currTunnel.flow_rate);
  94.             moves.push((Node {
  95.                 currentLoc: x.currentLoc,
  96.                 valves_opened: newValveOpenedList,
  97.                 time: next_time,
  98.                 totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  99.             }, LARGE_NUM - deltaPressure as u32));
  100.         }
  101.  
  102.         for tun in &currTunnel.tunnels
  103.         {
  104.             //we add each move option here
  105.             moves.push((Node {
  106.                 currentLoc: *tun,
  107.                 valves_opened: x.valves_opened.clone(),
  108.                 time: next_time,
  109.                 totalPressureRelieved: x.totalPressureRelieved
  110.             }, LARGE_NUM ));
  111.         }
  112.         moves
  113.  
  114.     }, |x|
  115.         {
  116.             // you are able to set this to 29 since the last minute you cant do anything that helps you
  117.             x.time == 29
  118.         }
  119.     ).unwrap();
  120.     println!("{}", res.0.last().unwrap().totalPressureRelieved);
  121.  
  122. }
  123.  
  124.  
  125. pub fn day16_2()
  126. {
  127.     let (tempMap, tunnelMap2) = genTunnelMap();
  128.     const LARGE_NUM: u32 = 1000000;
  129.     let allPaths = dijkstra_all(&Node {
  130.         currentLoc: *tempMap.get(&"AA".to_string()).unwrap(),
  131.         valves_opened: Default::default(),
  132.         time: 1,
  133.         totalPressureRelieved: 0
  134.     }, |x| {
  135.         let mut moves = vec![];
  136.         if x.time == 25
  137.         {
  138.             // we don't allow any moves after 26 steps
  139.             //you are able to set this to 25 since the last minute you cant do anything that helps you
  140.             return moves;
  141.         }
  142.         let next_time = x.time+1;
  143.         let currTunnel = tunnelMap2.get(&x.currentLoc).unwrap();
  144.         if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(&x.currentLoc))
  145.         {
  146.             let mut newValveOpenedList = x.valves_opened.clone();
  147.             newValveOpenedList.insert(x.currentLoc);
  148.             // we add the opening valve move here
  149.             let deltaPressure = ((26 - x.time as u16) * currTunnel.flow_rate);
  150.             moves.push((Node {
  151.                 currentLoc: x.currentLoc,
  152.                 valves_opened: newValveOpenedList,
  153.                 time: next_time,
  154.                 totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  155.             }, LARGE_NUM - deltaPressure as u32));
  156.         }
  157.  
  158.         for tun in &currTunnel.tunnels
  159.         {
  160.             //we add each move option here
  161.             moves.push((Node {
  162.                 currentLoc: *tun,
  163.                 valves_opened: x.valves_opened.clone(),
  164.                 time: next_time,
  165.                 totalPressureRelieved: x.totalPressureRelieved
  166.             }, LARGE_NUM ));
  167.         }
  168.         moves
  169.     }
  170.     );
  171.     let mut valveSetToPressureMap: HashMap<_, _> = Default::default();
  172.     allPaths.iter().for_each(|(node, _ )|{
  173.         if (node.time != 25) || (node.totalPressureRelieved == 0) //|| (node.valves_opened.len() < 3)
  174.         {
  175.             return;
  176.         }
  177.         if !valveSetToPressureMap.contains_key(&node.valves_opened) || *valveSetToPressureMap.index(&node.valves_opened) < node.totalPressureRelieved
  178.         {
  179.             valveSetToPressureMap.insert(&node.valves_opened, node.totalPressureRelieved);
  180.         }
  181.     });
  182.      let ans: u16 = valveSetToPressureMap.iter().cartesian_product(&valveSetToPressureMap).map(|x| {
  183.          if x.0.0.is_disjoint(x.1.0) {
  184.              x.0.1 + x.1.1
  185.          }
  186.          else {
  187.              0
  188.          }
  189.      }).max().unwrap();
  190.     println!("{}", ans);
  191. }
  192.  
  193.  
  194. #[derive(Eq, PartialEq, Hash, Clone, Debug)]
  195. struct Node2
  196. {
  197.     currentLocs: BTreeSet<u8>,
  198.     valves_opened: BTreeSet<u8>,
  199.     time:u8,
  200.     //this calculates from the moment you close a valve
  201.     totalPressureRelieved: u16,
  202. }
  203. pub fn day16_2_too_much_memory(){
  204.     let (tempMap, tunnelMap2) = genTunnelMap();
  205.     const LARGE_NUM: u32 = 1000000;
  206.     let res = dijkstra(&Node2 {
  207.         currentLocs: BTreeSet::from([*tempMap.get(&"AA".to_string()).unwrap()]),
  208.         valves_opened: Default::default(),
  209.         time: 1,
  210.         totalPressureRelieved: 0
  211.     }, |x| {
  212.         let mut moves = vec![];
  213.         let next_time = x.time+1;
  214.         //case where elephant and I am in different tunnels
  215.         if x.currentLocs.len() == 2 {
  216.             let firstLoc = x.currentLocs.first().unwrap();
  217.             let secondLoc = x.currentLocs.last().unwrap();
  218.             let currTunnel1 = tunnelMap2.get(firstLoc).unwrap();
  219.             let currTunnel2 = tunnelMap2.get(secondLoc).unwrap();
  220.             //case where we both open valves
  221.             if (currTunnel1.flow_rate != 0) && (!x.valves_opened.contains(firstLoc)) &&
  222.                 (currTunnel2.flow_rate != 0) && (!x.valves_opened.contains(secondLoc))
  223.             {
  224.                 let mut newValveOpenedList = x.valves_opened.clone();
  225.                 newValveOpenedList.extend([firstLoc, secondLoc]);
  226.                 // we add the opening valve move here
  227.                 let deltaPressure = ((26 - x.time as u16) * currTunnel1.flow_rate) + ((26 - x.time as u16) * currTunnel2.flow_rate);
  228.                 moves.push((Node2 {
  229.                     currentLocs: x.currentLocs.clone(),
  230.                     valves_opened: newValveOpenedList,
  231.                     time: next_time,
  232.                     totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  233.                 }, LARGE_NUM - deltaPressure as u32));
  234.             }
  235.             //case where we open only first valve
  236.             if (currTunnel1.flow_rate != 0) && (!x.valves_opened.contains(firstLoc))
  237.             {
  238.                 let mut newValveOpenedList = x.valves_opened.clone();
  239.                 newValveOpenedList.insert(*firstLoc);
  240.                 let deltaPressure = ((26 - x.time as u16) * currTunnel1.flow_rate);
  241.                 for tun in &currTunnel2.tunnels
  242.                 {
  243.                     moves.push((Node2 {
  244.                         currentLocs: BTreeSet::from([*firstLoc, *tun]),
  245.                         valves_opened: newValveOpenedList.clone(),
  246.                         time: next_time,
  247.                         totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  248.                     }, LARGE_NUM - deltaPressure as u32));
  249.                 }
  250.             }
  251.             //case where we open only second valve
  252.             if (currTunnel2.flow_rate != 0) && (!x.valves_opened.contains(secondLoc))
  253.             {
  254.                 let mut newValveOpenedList = x.valves_opened.clone();
  255.                 newValveOpenedList.insert(*secondLoc);
  256.                 let deltaPressure = ((26 - x.time as u16) * currTunnel2.flow_rate);
  257.                 for tun in &currTunnel1.tunnels
  258.                 {
  259.                     moves.push((Node2 {
  260.                         currentLocs: BTreeSet::from([*secondLoc, *tun]),
  261.                         valves_opened: newValveOpenedList.clone(),
  262.                         time: next_time,
  263.                         totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  264.                     }, LARGE_NUM - deltaPressure as u32));
  265.                 }
  266.             }
  267.             // case where we both move
  268.             for (newtun1, newtun2) in currTunnel1.tunnels.iter().cartesian_product(&currTunnel2.tunnels) {
  269.                 moves.push((Node2 {
  270.                     currentLocs: BTreeSet::from([*newtun1, *newtun2]),
  271.                     valves_opened: x.valves_opened.clone(),
  272.                     time: next_time,
  273.                     totalPressureRelieved: x.totalPressureRelieved
  274.                 }, LARGE_NUM));
  275.             }
  276.         }
  277.         //case where we are both in the same place
  278.         else if x.currentLocs.len() == 1
  279.         {
  280.             let loc = x.currentLocs.first().unwrap();
  281.             let currTunnel = tunnelMap2.get(loc).unwrap();
  282.             //case where one of us opens the valve
  283.             if (currTunnel.flow_rate != 0) && (!x.valves_opened.contains(loc))
  284.             {
  285.                 let mut newValveOpenedList = x.valves_opened.clone();
  286.                 newValveOpenedList.insert(*loc);
  287.                 let deltaPressure = ((26 - x.time as u16) * currTunnel.flow_rate);
  288.                 for tun in &currTunnel.tunnels
  289.                 {
  290.                     moves.push((Node2 {
  291.                         currentLocs: BTreeSet::from([*loc, *tun]),
  292.                         valves_opened: newValveOpenedList.clone(),
  293.                         time: next_time,
  294.                         totalPressureRelieved: x.totalPressureRelieved + deltaPressure
  295.                     }, LARGE_NUM - deltaPressure as u32));
  296.                 }
  297.             }
  298.             //case where we both move
  299.             for (newtun1, newtun2) in currTunnel.tunnels.iter().cartesian_product(&currTunnel.tunnels) {
  300.                 moves.push((Node2 {
  301.                     currentLocs: BTreeSet::from([*newtun1, *newtun2]),
  302.                     valves_opened: x.valves_opened.clone(),
  303.                     time: next_time,
  304.                     totalPressureRelieved: x.totalPressureRelieved
  305.                 }, LARGE_NUM));
  306.             }
  307.         }
  308.         moves
  309.  
  310.     }, |x|
  311.         {
  312.             // you are able to set this to 25 since the last minute you or the elephant cant do anything that helps you
  313.             x.time == 26
  314.         }
  315.     ).unwrap();
  316.     println!("{:?}", res.0);
  317.     println!("{}", res.0.last().unwrap().totalPressureRelieved);
  318. }
  319.  
  320.  
  321.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement