Advertisement
krzysz00

Advent of code, day 7

Dec 9th, 2017
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.34 KB | None | 0 0
  1. #![feature(conservative_impl_trait)]
  2. use std::io::{stdin,BufRead};
  3. use std::collections::hash_map::{HashMap,Entry};
  4.  
  5. #[derive(Clone,Debug,PartialEq,Eq)]
  6. struct Node {
  7.     pub name: String,
  8.     pub weight: u32,
  9.     // Per spec:
  10.     // sum_{c in children} weight[c]
  11.     // + if (not leaf(c)) recursive_weight[c]
  12.     pub recursive_weight: Option<u32>,
  13.     pub parent: Option<usize>,
  14.     pub children: Vec<usize>
  15. }
  16.  
  17. impl Node {
  18.     pub fn new(name: String, weight: u32) -> Self {
  19.         Node { name: name, weight: weight,
  20.                recursive_weight: None,
  21.                parent: None, children: Vec::new() }
  22.     }
  23. }
  24.  
  25. #[derive(Clone,Debug,PartialEq,Eq,Default)]
  26. struct Forest {
  27.     fast_lookup: HashMap<String, usize>,
  28.     nodes: Vec<Node>
  29. }
  30.  
  31. impl Forest {
  32.     pub fn new() -> Self {
  33.         Default::default()
  34.     }
  35.  
  36.     pub fn insert(&mut self, name: String, weight: u32) {
  37.         let node = Node::new(name.clone(), weight);
  38.         let node_idx = self.nodes.len();
  39.         self.nodes.push(node);
  40.         self.fast_lookup.insert(name, node_idx);
  41.     }
  42.  
  43.     pub fn set_children(&mut self, node: &String, children: &[String]) {
  44.         let parent_idx = self.fast_lookup[node];
  45.         for child in children {
  46.             let child_idx = self.fast_lookup[child];
  47.             self.nodes[child_idx].parent = Some(parent_idx);
  48.             self.nodes[parent_idx].children.push(child_idx);
  49.         }
  50.     }
  51.  
  52.     pub fn root(&self) -> String {
  53.         self.nodes.iter().filter_map(
  54.             |x| if x.parent.is_some() { None }
  55.                 else { Some(x.name.clone()) }
  56.         ).next().unwrap()
  57.     }
  58.  
  59.     fn recursive_weight_calc(&mut self, node: usize) {
  60.         let mut rec_weight = self.nodes[node].weight;
  61.         for child_idx in self.nodes[node].children.clone() {
  62.             if self.nodes[child_idx].recursive_weight.is_none() {
  63.                 self.recursive_weight_calc(child_idx);
  64.             }
  65.             rec_weight += self.nodes[child_idx].recursive_weight.unwrap();
  66.         }
  67.         self.nodes[node].recursive_weight = Some(rec_weight);
  68.     }
  69.  
  70.     pub fn fill_weights(&mut self, root: &String) {
  71.         let root_idx = self.fast_lookup[root];
  72.         self.recursive_weight_calc(root_idx);
  73.     }
  74.  
  75.     fn recursive_solve(&self, node: usize,
  76.                        parent_canonical: Option<u32>) -> Option<u32> {
  77.         let mut distinct_weights = HashMap::<u32, Option<usize>>::new();
  78.         let mut canonical_weight: Option<u32> = None;
  79.         for child in self.nodes[node].children.clone() {
  80.             let weight = self.nodes[child].recursive_weight.expect("Weights are filled");
  81.             let mut entry = distinct_weights.entry(weight);
  82.             match entry {
  83.                 Entry::Occupied(mut o) => if o.get().is_some() {
  84.                     o.insert(None);
  85.                     canonical_weight = Some(weight);
  86.                 },
  87.                 Entry::Vacant(mut v) => { v.insert(Some(child)); },
  88.             }
  89.         }
  90.         distinct_weights.retain(|_, v| v.is_some());
  91.  
  92.         let results: HashMap<u32, u32>
  93.             = distinct_weights.iter().filter_map(
  94.                 |(k, s_v)| self.recursive_solve(s_v.unwrap(), canonical_weight)
  95.                     .map(|x| (*k, x)))
  96.             .collect();
  97.         if results.len() == 1 {
  98.             Some(*results.values().next().unwrap())
  99.         }
  100.         else if results.is_empty() {
  101.             if distinct_weights.len() == 2 {
  102.                 panic!("Ambiguity in the binary tree case");
  103.             }
  104.             else {
  105.                 parent_canonical.map(
  106.                     |mut big_w| {
  107.                         for i in self.nodes[node].children.clone() {
  108.                             big_w -= self.nodes[i].recursive_weight.unwrap();
  109.                         }
  110.                         big_w
  111.                     })
  112.             }
  113.         }
  114.         else {
  115.             panic!("We didn't forsee this case");
  116.         }
  117.     }
  118.  
  119.     pub fn solve(&self, root: &String) -> u32 {
  120.         let root_idx = self.fast_lookup[root];
  121.         self.recursive_solve(root_idx, None).unwrap()
  122.     }
  123. }
  124.  
  125.  
  126. fn main() {
  127.     let stdin = stdin();
  128.     let stdin = stdin.lock();
  129.     let mut tree = Forest::new();
  130.     let mut child_map = HashMap::<String, Vec<String>>::new();
  131.     for line in stdin.lines() {
  132.         let line = line.expect("Error reading stdin");
  133.         let mut words = line.split_whitespace();
  134.         let name = words.next().expect("Missing name").to_owned();
  135.         let weight_str = words.next().expect("Missing weight");
  136.         let weight: u32 = weight_str[1..weight_str.len()-1].parse()
  137.             .expect("Non-integer weight");
  138.  
  139.         if let Some(_) = words.next() {
  140.             let mut child_vec = Vec::new();
  141.             for child in words {
  142.                 let mut child = child.to_owned();
  143.                 if child.ends_with(',') {
  144.                     child.pop();
  145.                 }
  146.                 child_vec.push(child);
  147.             }
  148.             child_map.insert(name.clone(), child_vec);
  149.         }
  150.  
  151.         tree.insert(name, weight);
  152.     }
  153.  
  154.     for (parent, children) in &child_map {
  155.         tree.set_children(parent, children);
  156.     }
  157.  
  158.     let root = tree.root();
  159.     println!("root: {}", root);
  160.     tree.fill_weights(&root);
  161.     let new_weight = tree.solve(&root);
  162.     println!("new weight: {}", new_weight);
  163. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement