Skip to content

Commit

Permalink
puzzles/day_7: Refactor code into parse_rules()
Browse files Browse the repository at this point in the history
Both part 1 and part 2 used this code, thus refactored into its own function.

Signed-off-by: Jim Gerth <[email protected]>
  • Loading branch information
jimgerth committed Jan 3, 2021
1 parent c59bcee commit b32a833
Showing 1 changed file with 37 additions and 64 deletions.
101 changes: 37 additions & 64 deletions src/puzzles/day_7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,28 @@ use super::input;

pub fn part_1() -> i32 {
let input = input::read_lines(7);
let mut can_contain_rules: HashMap<&str, HashSet<&str>> = HashMap::new();
let contains_rules = parse_rules(input.iter().map(|line| line.as_str()).collect());
let mut contained_in_rules: HashMap<&str, HashSet<&str>> = HashMap::new();

let bag_color_regex = Regex::new(r"^\w* \w*").unwrap();
let bag_rules_regex = Regex::new(r"bags contain (.*).").unwrap();
let bag_rule_regex = Regex::new(r"\d+ (\w+ \w+) \w+").unwrap();

// Parse rules.
for line in &input {
let bag_color = bag_color_regex
.captures(line)
.unwrap()
.get(0)
.unwrap()
.as_str();
let bag_rules = bag_rules_regex
.captures(line)
.unwrap()
.get(1)
.unwrap()
.as_str();

let bag_rules: HashSet<&str> = if bag_rules != "no other bags" {
bag_rules
.split(", ")
.map(|rule| {
bag_rule_regex
.captures(rule)
.unwrap()
.get(1)
.unwrap()
.as_str()
})
.collect()
} else {
HashSet::new()
};

can_contain_rules.insert(bag_color, bag_rules);
contained_in_rules.insert(bag_color, HashSet::new());
}

// println!("{:#?}", can_contain_rules);

// Invert rules.
for (color, contained_colors) in can_contain_rules.iter() {
for contained_color in contained_colors {
contained_in_rules
.get_mut(contained_color)
.unwrap()
.insert(color);
for (container_color, contains_rule) in contains_rules {
// println!("{:?} contains", container_color);
for (contained_color, _) in contains_rule {
// println!("\t{:?}", contained_color);
match contained_in_rules.get_mut(contained_color) {
Some(contained_in_rule) => {
contained_in_rule.insert(container_color);
}
None => {
let mut contained_in_rule = HashSet::new();
contained_in_rule.insert(container_color);
contained_in_rules.insert(contained_color, contained_in_rule);
}
}
}
}

// println!("{:#?}", contained_in_rules);
println!("{:#?}", contained_in_rules);

let containers = get_containers("shiny gold", &contained_in_rules);

Expand All @@ -69,13 +36,20 @@ pub fn part_1() -> i32 {
containers.len() as i32
}

pub fn part_2() -> i32 {
let input = input::read_lines(7);
let rules = parse_rules(input.iter().map(|line| line.as_str()).collect());
get_content_count("shiny gold", &rules)
}

fn get_containers<'a>(
color: &'a str,
contained_in_rules: &'a HashMap<&str, HashSet<&str>>,
) -> HashSet<&'a str> {
let directly_contained_in = contained_in_rules
.get(color)
.expect("Color not listed in rules.");
let directly_contained_in = match contained_in_rules.get(color) {
Some(contained_in) => contained_in.clone(),
None => HashSet::new(),
};
let mut contained_in = directly_contained_in.clone();
for color in directly_contained_in {
contained_in = contained_in
Expand All @@ -86,8 +60,16 @@ fn get_containers<'a>(
contained_in
}

pub fn part_2() -> i32 {
let input = input::read_lines(7);
fn get_content_count(color: &str, rules: &HashMap<&str, HashMap<&str, i32>>) -> i32 {
let rule = rules.get(color).expect("Color not listed in rules.");
let mut total = 0;
for (color, count) in rule {
total += count + count * get_content_count(color, &rules);
}
total
}

fn parse_rules(input: Vec<&str>) -> HashMap<&str, HashMap<&str, i32>> {
let mut rules: HashMap<&str, HashMap<&str, i32>> = HashMap::new();

let bag_color_regex = Regex::new(r"^\w* \w*").unwrap();
Expand Down Expand Up @@ -140,14 +122,5 @@ pub fn part_2() -> i32 {

// println!("{:#?}", rules);

get_content_count("shiny gold", &rules)
}

fn get_content_count(color: &str, rules: &HashMap<&str, HashMap<&str, i32>>) -> i32 {
let rule = rules.get(color).expect("Color not listed in rules.");
let mut total = 0;
for (color, count) in rule {
total += count + count * get_content_count(color, &rules);
}
total
rules
}

0 comments on commit b32a833

Please sign in to comment.