Advertisement
Guest User

Untitled

a guest
Dec 16th, 2022
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.68 KB | Software | 0 0
  1.  
  2. use std::cmp::Ordering;
  3. use std::collections::{HashMap, VecDeque};
  4. use std::time::Instant;
  5.  
  6. use aoc_parse::{parser, prelude::*};
  7.  
  8. const MAX_DISTANCE: u8 = 26;
  9. const PART_COUNT: usize = 2;
  10.  
  11. #[derive(Copy, Clone, Debug)]
  12. struct Node {
  13.     v_id: u8,
  14.     distance: [u8; 64]
  15. }
  16.  
  17. impl Node {
  18.  
  19.     fn new(v_id: u8) -> Self {
  20.         Self {
  21.             v_id,
  22.             distance: [u8::MAX; 64]
  23.         }
  24.     }
  25.  
  26.     fn build_node(&mut self, edge_map: &[u64]) {
  27.         let mut queue = VecDeque::new();
  28.         let mut visited = 0u64;
  29.  
  30.         queue.push_back((self.v_id, 1));
  31.         while let Some((c_v_id, distance)) = queue.pop_front() {
  32.             if (visited & (1 << c_v_id)) != 0 {
  33.                 continue;
  34.             }
  35.  
  36.             visited |= 1 << c_v_id;
  37.             self.distance[c_v_id as usize] = distance;
  38.  
  39.             let edges = edge_map[c_v_id as usize];
  40.             for i in 0..64 {
  41.                 if (edges & (1 << i)) != 0 {
  42.                     queue.push_back((i, distance + 1));
  43.                 }
  44.             }
  45.         }
  46.     }
  47.  
  48. }
  49.  
  50. struct Cache {
  51.     backing_array: Vec<u16>,
  52.     node_count: usize
  53. }
  54.  
  55. impl Cache {
  56.  
  57.     fn new(node_count: usize) -> Self {
  58.         let mut array_size = PART_COUNT;
  59.         array_size *= (MAX_DISTANCE + 1) as usize;
  60.         array_size *= 1 << node_count;
  61.         array_size *= node_count;
  62.  
  63.         println!("Cache size: {}", array_size);
  64.  
  65.         Self {
  66.             backing_array: vec![u16::MAX; array_size],
  67.             node_count
  68.         }
  69.     }
  70.  
  71.     fn to_index(&self, participant: usize, rem_distance: u8, current_node: usize, turned_valves: usize) -> usize {
  72.         let mut array_index = participant;
  73.         array_index = (array_index * ((MAX_DISTANCE + 1) as usize)) + (rem_distance as usize);
  74.         array_index = (array_index * (1 << self.node_count)) + turned_valves;
  75.         array_index = (array_index * self.node_count) + current_node;
  76.         array_index
  77.     }
  78.  
  79.     fn get_value(&self, index: usize) -> u16 {
  80.         unsafe { *self.backing_array.get_unchecked(index) }
  81.     }
  82.  
  83.     fn set_value(&mut self, index: usize, value: u16) {
  84.         unsafe { *self.backing_array.get_unchecked_mut(index) = value; }
  85.     }
  86.  
  87. }
  88.  
  89. fn get_max_flow(participant: usize, rem_distance: u8, current_node: usize, turned_valves: usize, nodes: &[Node], v_rates: &[u16], cache: &mut Cache) -> u16 {
  90.     let index = cache.to_index(participant, rem_distance, current_node, turned_valves);
  91.     if cache.get_value(index) == u16::MAX {
  92.         let mut max_flow = 0;
  93.        
  94.         let node = &nodes[current_node];
  95.         for i in 1..cache.node_count {
  96.             if (turned_valves & (1 << i)) != 0 {
  97.                 continue;
  98.             }
  99.  
  100.             if node.distance[i] >= rem_distance {
  101.                 continue;
  102.             }
  103.  
  104.             let next_flow =
  105.                 get_max_flow(
  106.                     participant,
  107.                     rem_distance - node.distance[i],
  108.                     i,
  109.                     turned_valves | (1 << i),
  110.                     nodes,
  111.                     v_rates,
  112.                     cache);
  113.  
  114.             max_flow = std::cmp::max(max_flow, next_flow);
  115.         }
  116.  
  117.         if participant != 0 {
  118.             let next_flow =
  119.                 get_max_flow(
  120.                     participant - 1,
  121.                     MAX_DISTANCE,
  122.                     0,
  123.                     turned_valves,
  124.                     nodes,
  125.                     v_rates,
  126.                     cache);
  127.  
  128.             max_flow = std::cmp::max(max_flow, next_flow);
  129.         }
  130.  
  131.         max_flow += v_rates[current_node] * (rem_distance as u16);
  132.         cache.set_value(index, max_flow);
  133.     }
  134.  
  135.     cache.get_value(index)
  136. }
  137.  
  138. fn main() {
  139.     let input = std::io::read_to_string(std::io::stdin().lock()).unwrap();
  140.  
  141.     let parser =
  142.         parser!(lines("Valve " string(alpha+) " has flow rate=" u16 "; tunnel" "s"? " lead" "s"? " to valve" "s"? " " repeat_sep(string(alpha+), ", ") "\r"?));
  143.  
  144.     let mut input =
  145.         parser
  146.         .parse(&input)
  147.         .unwrap()
  148.         .into_iter()
  149.         .map(|(v_id, rate, _, _, _, edges, _)| (v_id, rate, edges))
  150.         .collect::<Vec<_>>();
  151.  
  152.     input
  153.     .sort_by(|l, r| {
  154.         if l.0 == "AA" {
  155.             return Ordering::Less;
  156.  
  157.         } else if r.0 == "AA" {
  158.             return Ordering::Greater;
  159.         }
  160.  
  161.         r.1.cmp(&l.1).then(l.0.cmp(&r.0))
  162.     });
  163.  
  164.     let mut v_id_map = HashMap::new();
  165.     let mut v_rates = Vec::new();
  166.     let mut v_edges = Vec::new();
  167.     let mut nodes = Vec::new();
  168.     let mut interesting_nodes = 1;
  169.     for (v_id, rate, edges) in input {
  170.         nodes.push(Node::new(v_id_map.len() as u8));
  171.         v_id_map.insert(v_id.clone(), v_id_map.len() as u8);
  172.         v_rates.push(rate);
  173.         v_edges.push(edges);
  174.         if rate != 0 {
  175.             interesting_nodes += 1;
  176.         }
  177.     }
  178.  
  179.     let v_edges =
  180.         v_edges
  181.         .into_iter()
  182.         .map(|edges| {
  183.             let mut edge_mask = 0;
  184.             for edge in edges {
  185.                 let edge_id = v_id_map.get(&edge).unwrap();
  186.                 edge_mask |= 1 << edge_id;
  187.             }
  188.  
  189.             edge_mask
  190.         })
  191.         .collect::<Vec<_>>();
  192.  
  193.     let start = Instant::now();
  194.     let mut cache = Cache::new(interesting_nodes);
  195.     for node in &mut nodes[0..interesting_nodes] {
  196.         node.build_node(&v_edges);
  197.     }
  198.  
  199.     let max_flow =
  200.         get_max_flow(
  201.             PART_COUNT - 1,
  202.             MAX_DISTANCE,
  203.             0,
  204.             0,
  205.             &nodes,
  206.             &v_rates,
  207.             &mut cache);
  208.  
  209.     println!("{}", max_flow);
  210.    
  211.     let end = Instant::now();
  212.     println!("{:?}", end - start);
  213.  
  214. }
  215.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement