2020-12-07 - Handy Haversacks
(original .ipynb)
Day 7 puzzle input is a list of descriptions of coloured bags and what colours of bags they can contain (mine is here). Part 1 involve s finding all the bag colours that may directly or indirectly contain a "shiny gold" bag. Part 2 involves finding the total number of bags that are inside a "shiny gold" bag.
import re def parse_bag_str(bag_str): m = re.search("(\d+ |no )?(\w+) (\w+) bags?.?", bag_str) return (m.group(1), m.group(2), m.group(3)) class Bag: def __init__(self, bag_str, parent=None): quantity, adjective1, adjective2 = parse_bag_str(bag_str) self.quantity = int(quantity) if quantity else 0 self.color = adjective1 + " " + adjective2 self.parent = parent self.children = [] def add_child(self, child): if child.color != "no other": self.children.append(child) def parse_line(line): parent_str, children_str = line.split("contain") parent = Bag(parent_str) for child_str in children_str.split(", "): child = Bag(child_str, parent) parent.add_child(child) return parent def contains_color(bag, bag_lookup, color="shiny gold"): if not bag.children: return False directly_contains_color = color in [c.color for c in bag.children] indirectly_contains_color = any( contains_color(bag_lookup[c.color], bag_lookup, color) for c in bag.children) return directly_contains_color or indirectly_contains_color def parse_input_str(input_str): bag_lookup = {} all_bags = [] for line in input_str.split("\n"): bag = parse_line(line) all_bags += [bag] + bag.children bag_lookup[bag.color] = bag return (all_bags, bag_lookup) test_input_str = """light red bags contain 1 bright white bag, 2 muted yellow bags. dark orange bags contain 3 bright white bags, 4 muted yellow bags. bright white bags contain 1 shiny gold bag. muted yellow bags contain 2 shiny gold bags, 9 faded blue bags. shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags. dark olive bags contain 3 faded blue bags, 4 dotted black bags. vibrant plum bags contain 5 faded blue bags, 6 dotted black bags. faded blue bags contain no other bags. dotted black bags contain no other bags.""" puzzle_input_str = open("puzzle_input/day7.txt", "r").read().strip() def part1(input_str): all_bags, bag_lookup = parse_input_str(input_str) holding_target_color = set() for bag in all_bags: if contains_color(bag, bag_lookup): holding_target_color.add(bag.color) return len(holding_target_color) assert 4 == part1(test_input_str) print(part1(puzzle_input_str))
378
test_input_str_2 = """shiny gold bags contain 2 dark red bags. dark red bags contain 2 dark orange bags. dark orange bags contain 2 dark yellow bags. dark yellow bags contain 2 dark green bags. dark green bags contain 2 dark blue bags. dark blue bags contain 2 dark violet bags. dark violet bags contain no other bags.""" def count_bag_totals(bag, bag_lookup): if len(bag.children) == 0: return 0 return sum([c.quantity + (c.quantity * count_bag_totals(bag_lookup[c.color], bag_lookup)) for c in bag.children]) def part2(input_str): all_bags, bag_lookup = parse_input_str(input_str) return count_bag_totals(bag_lookup["shiny gold"], bag_lookup) assert 126 == part2(test_input_str_2) print(part2(puzzle_input_str))
27526