[TASK] (finally) solved Day 7

This commit is contained in:
2020-12-07 21:51:25 +01:00
parent 9e0b4dbcd5
commit d2cdb9a0c6
6 changed files with 761 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ pub fn solve() {
let valid_count2 = raw_fields.iter()
.filter(|rf| is_valid(rf))
// .inspect(|p| println!("{}\n", p.join(" ")))
.count();
println!("Day 4 Part 2: {}", valid_count2);

147
src/day7.rs Normal file
View File

@@ -0,0 +1,147 @@
use super::util;
use regex::{Regex, Captures};
use std::collections::{HashMap, HashSet, VecDeque};
pub fn solve() {
let lines = util::read_file("input/day7.txt");
let rules = lines.iter()
.map(|s| Rule::parse(s))
// .inspect(|r| println!("{:?}", r))
.collect::<Vec<_>>();
let mut reverse_rules: HashMap<String, Vec<&Rule>> = HashMap::new();
for rule in &rules {
for bag_set in &rule.contains {
reverse_rules.entry(String::from(&bag_set.bag_color)).and_modify(|e| e.push(&rule)).or_insert_with(|| vec!(&rule));
}
}
let enclosing_bag_colors = find_enclosing_bag_colors("shiny gold", &reverse_rules);
println!("Day 7 Part 1: {}", enclosing_bag_colors.len());
let part2 = count_bags("shiny gold", &rules);
println!("Day 7 Part 2: {}", part2 - 1);
}
fn find_enclosing_bag_colors(root_color: &str, reverse_rules: &HashMap<String, Vec<&Rule>>) -> HashSet<String> {
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();
colors_to_check.push_front(String::from(root_color));
let empty: Vec<&Rule> = Vec::new();
while !colors_to_check.is_empty() {
let cur = colors_to_check.pop_back().unwrap();
marked_colors.insert(String::from(&cur));
let cur_rules = reverse_rules.get(&cur).unwrap_or(&empty);
for rule in cur_rules {
let rule_color = String::from(&rule.bag_color);
if !marked_colors.contains(&rule_color) {
colors_to_check.push_front(String::from(&rule_color));
};
marked_colors.insert(String::from(&rule_color));
enclosing_bag_colors.insert(String::from(&rule_color));
}
}
enclosing_bag_colors
}
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 mut rule_map: HashMap<&String, &Rule> = HashMap::new();
for rule in rules {
rule_map.insert(&rule.bag_color, &rule);
}
let root = String::from(root_color);
let mut cache: HashMap<String, usize> = HashMap::new();
let res = count_bags_recursive( &root, &rule_map, &mut cache);
// println!("{:?}", cache);
res
}
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);
return if cached.is_some() {
*cached.unwrap()
} else if rule.contains.is_empty() {
cache.insert(String::from(root_color), 1);
1
} else {
let mut res = 1;
for bag in &rule.contains {
res += bag.amount * count_bags_recursive(&bag.bag_color, &rule_map, cache);
}
cache.insert(String::from(root_color), res);
res
}
}
#[derive(Debug)]
struct Rule {
bag_color: String,
contains: Vec<BagSet>
}
#[derive(Debug)]
struct BagSet {
amount: usize,
bag_color: String
}
lazy_static! {
static ref RULE_MATCHER: Regex = Regex::new(r"^([a-z]+ [a-z]+) bags contain ((?:no other bags)|(?:[0-9]+ [a-z]+ [a-z]+ bags?(?:, )?)+).$").unwrap();
static ref BAGSET_MATCHER: Regex = Regex::new(r"^([0-9]+) ([a-z]+ [a-z]+) bags?$").unwrap();
}
impl Rule {
pub fn parse(input: &String) -> Rule {
let rule_caps = RULE_MATCHER.captures(input.as_str()).unwrap();
let bag_sets_input = Rule::get_str_capture(&rule_caps, 2);
let bag_sets = Rule::parse_bag_sets(&bag_sets_input);
return Rule {
bag_color: Rule::get_str_capture(&rule_caps, 1),
contains: bag_sets
}
}
fn parse_bag_sets(input: &String) -> Vec<BagSet> {
if input == "no other bags" {
return Vec::new();
}
return input.split(", ")
.map(|bs| Rule::parse_bag_set(bs))
.collect::<Vec<_>>();
}
fn parse_bag_set(input: &str) -> BagSet {
let caps = BAGSET_MATCHER.captures(input).unwrap();
return BagSet {
amount: Rule::get_usize_capture(&caps, 1),
bag_color: Rule::get_str_capture(&caps, 2)
}
}
fn get_str_capture(caps: &Captures, id: usize) -> String {
return caps.get(id).map_or(String::from(""), |m| String::from(m.as_str()));
}
fn get_usize_capture(caps: &Captures, id: usize) -> usize {
return caps.get(id).map_or(0, |m| m.as_str().parse::<usize>().unwrap());
}
}

View File

@@ -8,6 +8,7 @@ mod day3;
mod day4;
mod day5;
mod day6;
mod day7;
fn main() {
@@ -24,6 +25,7 @@ fn main() {
4 => day4::solve(),
5 => day5::solve(),
6 => day6::solve(),
7 => day7::solve(),
_ => println!("This day is not yet implemented")
}
} else {
@@ -34,6 +36,7 @@ fn main() {
day4::solve();
day5::solve();
day6::solve();
day7::solve();
}
println!("Execution took {} μs", now.elapsed().as_micros());