[TASK] Some small performance improvements in day 7 (like that was needed)
This commit is contained in:
55
src/day7.rs
55
src/day7.rs
@@ -1,14 +1,17 @@
|
|||||||
use super::util;
|
use super::util;
|
||||||
use regex::{Regex, Captures};
|
use regex::{Regex, Captures};
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
pub fn solve() {
|
pub fn solve() {
|
||||||
|
let now = Instant::now();
|
||||||
let lines = util::read_file("input/day7.txt");
|
let lines = util::read_file("input/day7.txt");
|
||||||
let rules = lines.iter()
|
let rules = lines.iter()
|
||||||
.map(|s| Rule::parse(s))
|
.map(|s| Rule::parse(s))
|
||||||
// .inspect(|r| println!("{:?}", r))
|
// .inspect(|r| println!("{:?}", r))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
||||||
let mut reverse_rules: HashMap<String, Vec<&Rule>> = HashMap::new();
|
let mut reverse_rules: HashMap<String, Vec<&Rule>> = HashMap::new();
|
||||||
for rule in &rules {
|
for rule in &rules {
|
||||||
|
|
||||||
@@ -17,64 +20,62 @@ pub fn solve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let enclosing_bag_colors = find_enclosing_bag_colors("shiny gold", &reverse_rules);
|
let enclosing_bag_colors = find_enclosing_bag_colors(&String::from("shiny gold"), &reverse_rules);
|
||||||
|
|
||||||
println!("Day 7 Part 1: {}", enclosing_bag_colors.len());
|
println!("Day 7 Part 1: {}", enclosing_bag_colors);
|
||||||
|
|
||||||
let part2 = count_bags("shiny gold", &rules);
|
let part2 = count_bags("shiny gold", &rules);
|
||||||
println!("Day 7 Part 2: {}", part2 - 1);
|
println!("Day 7 Part 2: {}", part2 - 1);
|
||||||
|
println!("Algo's took {} μs", now.elapsed().as_micros());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_enclosing_bag_colors(root_color: &str, reverse_rules: &HashMap<String, Vec<&Rule>>) -> HashSet<String> {
|
fn find_enclosing_bag_colors(root_color: &String, reverse_rules: &HashMap<String, Vec<&Rule>>) -> usize {
|
||||||
let mut enclosing_bag_colors: HashSet<String> = HashSet::new();
|
|
||||||
let mut marked_colors: HashSet<String> = HashSet::new();
|
|
||||||
|
|
||||||
let mut colors_to_check: VecDeque<String> = VecDeque::new();
|
let mut enclosing_bag_colors: HashSet<&String> = HashSet::new();
|
||||||
colors_to_check.push_front(String::from(root_color));
|
|
||||||
|
|
||||||
let empty: Vec<&Rule> = Vec::new();
|
let mut colors_to_check: VecDeque<&String> = VecDeque::new();
|
||||||
|
colors_to_check.push_front(root_color);
|
||||||
|
|
||||||
while !colors_to_check.is_empty() {
|
while !colors_to_check.is_empty() {
|
||||||
let cur = colors_to_check.pop_back().unwrap();
|
let cur = colors_to_check.pop_back().unwrap();
|
||||||
marked_colors.insert(String::from(&cur));
|
|
||||||
|
|
||||||
let cur_rules = reverse_rules.get(&cur).unwrap_or(&empty);
|
let cur_rules = reverse_rules.get(cur);
|
||||||
for rule in cur_rules {
|
if cur_rules.is_none() {
|
||||||
let rule_color = String::from(&rule.bag_color);
|
continue;
|
||||||
|
}
|
||||||
|
for rule in cur_rules.unwrap() {
|
||||||
|
let rule_color = &rule.bag_color;
|
||||||
|
|
||||||
if !marked_colors.contains(&rule_color) {
|
colors_to_check.push_front(&rule_color);
|
||||||
colors_to_check.push_front(String::from(&rule_color));
|
enclosing_bag_colors.insert(&rule_color);
|
||||||
};
|
|
||||||
marked_colors.insert(String::from(&rule_color));
|
|
||||||
enclosing_bag_colors.insert(String::from(&rule_color));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enclosing_bag_colors
|
enclosing_bag_colors.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_bags(root_color: &str, rules: &Vec<Rule>) -> usize {
|
fn count_bags(root_color: &str, rules: &Vec<Rule>) -> usize {
|
||||||
|
|
||||||
// Let's first create a dictionary to easily find the rules for each colored bag
|
// Let's first create a dictionary to easily find the rules for each colored bag
|
||||||
let mut rule_map: HashMap<&String, &Rule> = HashMap::new();
|
let mut rule_map: HashMap<&String, &Rule> = HashMap::new();
|
||||||
for rule in rules {
|
rules.iter().for_each(|r: &Rule| -> () { rule_map.insert(&r.bag_color, &r); });
|
||||||
rule_map.insert(&rule.bag_color, &rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
let root = String::from(root_color);
|
|
||||||
let mut cache: HashMap<String, usize> = HashMap::new();
|
let mut cache: HashMap<String, usize> = HashMap::new();
|
||||||
|
|
||||||
let res = count_bags_recursive( &root, &rule_map, &mut cache);
|
let res = count_bags_recursive( &String::from(root_color), &rule_map, &mut cache);
|
||||||
// println!("{:?}", cache);
|
// println!("{:?}", cache);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_bags_recursive(root_color: &String, rule_map: &HashMap<&String, &Rule>, cache: &mut HashMap<String, usize>) -> usize {
|
fn count_bags_recursive(root_color: &String, rule_map: &HashMap<&String, &Rule>, cache: &mut HashMap<String, usize>) -> usize {
|
||||||
|
|
||||||
let rule = rule_map.get(&root_color).unwrap();
|
|
||||||
let cached = cache.get(root_color);
|
let cached = cache.get(root_color);
|
||||||
return if cached.is_some() {
|
if cached.is_some() {
|
||||||
*cached.unwrap()
|
return *cached.unwrap()
|
||||||
} else if rule.contains.is_empty() {
|
}
|
||||||
|
|
||||||
|
let rule = rule_map.get(&root_color).unwrap();
|
||||||
|
return if rule.contains.is_empty() {
|
||||||
cache.insert(String::from(root_color), 1);
|
cache.insert(String::from(root_color), 1);
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user