Guest User

Untitled

a guest
Dec 9th, 2021
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.37 KB | None | 0 0
  1. use petgraph::Graph;
  2. use petgraph::graph::NodeIndex;
  3.  
  4. /// Get basin related to a given node.
  5. ///
  6. /// # Arguments
  7. ///
  8. /// * `graph` - The whole graph.
  9. /// * `node` - The current node position in the graph.
  10. /// * `result` - Where we store the basin currently seen elements.
  11. fn get_basin(graph: &Graph<i32, (), petgraph::Undirected>, node: &NodeIndex, result: &mut Vec<NodeIndex>) {
  12.     if result.contains(node) {
  13.         return;
  14.     }
  15.  
  16.     // We're sure its below 9 already there...
  17.     result.push(*node);
  18.  
  19.     for neighbor in graph.neighbors(*node) {
  20.         if graph[neighbor] < 9 {
  21.             get_basin(graph, &neighbor, result);
  22.         }
  23.     }
  24. }
  25.  
  26. fn aoc_09_part02(graph: &Graph<i32, (), petgraph::Undirected>) -> usize {
  27.     // Just to avoid doing too much algo... The seen isn't really needed as we already got basins...
  28.     let mut seen: Vec<NodeIndex> = Vec::new();
  29.     let mut basins: Vec<Vec<NodeIndex>> = Vec::new();
  30.  
  31.     graph.node_indices().into_iter().for_each(|idx| {
  32.         // Its a basin we haven't seen yet... So we trace it...
  33.         if graph[idx] < 9 && !seen.contains(&idx) {
  34.             // we find the basin
  35.             let mut basin: Vec<NodeIndex> = Vec::new();
  36.             get_basin(graph, &idx, &mut basin);
  37.  
  38.             if basin.len() > 0 {
  39.                 basins.push(basin.clone());
  40.                 for node in basin {
  41.                     if !seen.contains(&node) {
  42.                         seen.push(node);
  43.                     }
  44.                 }
  45.             }
  46.         }
  47.     });
  48.  
  49.     // Biggest first
  50.     basins.sort_unstable_by(|a, b| b.len().cmp(&a.len()));
  51.  
  52.     // Selecting top 3 only and multiply their length
  53.     basins[..=2].iter().fold(0, |acc, val| if acc == 0 { val.len() } else { acc * val.len() })
  54. }
  55.  
  56. fn aoc_09_part01(graph: &Graph<i32, (), petgraph::Undirected>) -> i32 {
  57.     let selected_nodes = graph.node_indices().into_iter().filter_map(|idx| {
  58.         let nodes = graph.neighbors(idx);
  59.         let node = graph[idx];
  60.         for sibling in nodes {
  61.             // The current node is not the minimum. We can stop here...
  62.             if graph[sibling] <= node {
  63.                 return None;
  64.             }
  65.         }
  66.  
  67.         // That's a minimum, we keep it...
  68.         Some(idx)
  69.     }).collect::<Vec<_>>();
  70.  
  71.     // The result is 1 + its height for each point
  72.     selected_nodes.iter().map(|idx| graph.node_weight(*idx).unwrap_or(&0) + 1).sum()
  73. }
  74.  
  75. macro_rules! create_edge {
  76.     ($graph: ident, $nodes: ident, $node: ident, $i: expr, $j: expr) => {
  77.         if $i >= 0 && $j >= 0 {
  78.             let el = $nodes.get($i as usize).and_then(|row| row.get($j as usize));
  79.             if el.is_some() {
  80.                 $graph.add_edge($node, *el.unwrap(), ());
  81.             }
  82.         }
  83.     }
  84. }
  85.  
  86. /// Convert vec of vec into a graph.
  87. ///
  88. /// # Arguments
  89. ///
  90. /// * `input` - The input to convert as a graph (petgraph)
  91. fn convert_to_graph(input: &[Vec<i32>]) -> Graph<i32, (), petgraph::Undirected> {
  92.     let mut deps = Graph::<i32, (), petgraph::Undirected>::new_undirected();
  93.  
  94.     // Creating graph nodes
  95.     let nodes = input.iter().map(|line| {
  96.         line.iter().map(|el| deps.add_node(*el)).collect::<Vec<_>>()
  97.     }).collect::<Vec<Vec<_>>>();
  98.  
  99.     // Creating graph edges
  100.     for i in 0..nodes.len() as i32 {
  101.         for j in 0..nodes[i as usize].len() as i32 {
  102.             let node = nodes[i as usize][j as usize];
  103.             // Up
  104.             create_edge!(deps, nodes, node, i - 1, j);
  105.             // Left
  106.             create_edge!(deps, nodes, node, i, j - 1);
  107.             // Its not a directed graph so we dont need to create dual sided links...
  108.             // so up/left is enough to model the structure.
  109.             // Down
  110.             // create_edge!(deps, nodes, node, i + 1, j);
  111.             // Right
  112.             // create_edge!(deps, nodes, node, i, j + 1);
  113.         }
  114.     }
  115.  
  116.     deps
  117. }
  118.  
  119. fn main() {
  120.     let s = include_str!("../input.txt").lines().map(|line| {
  121.         line.chars().filter_map(|c| c.to_string().parse::<i32>().ok()).collect::<Vec<_>>()
  122.     }).collect::<Vec<Vec<_>>>();
  123.  
  124.     // We convert this to a graph...
  125.     let graph = convert_to_graph(&s);
  126.     // println!("{:#?}", petgraph::dot::Dot::new(&graph));
  127.  
  128.     let result = aoc_09_part01(&graph);
  129.     println!("Result part 1: {}", result);
  130.  
  131.     let result = aoc_09_part02(&graph);
  132.     println!("Result part 2: {}", result);
  133. }
  134.  
Advertisement
Add Comment
Please, Sign In to add comment