⛄ Day 7

Advent of Code is a coding challenge that releases a puzzle every day starting December 1st up until the 25th - like an Advent Calendar but no stale chocolate...

Part 1

How many bag colors can eventually contain at least one shiny gold bag?
Solution:
                                
                                    
    # -- Rules --
    # 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.
    
    import csv
    
    
    def split_line(line):
        bags = line.split(' bags contain ')
    
        bag_p = bags[0]
        bag_c = bags[1]
        if bag_c == 'no other bags.':
            return {'bag': bag_p, 'rules': {}}
    
        bag_c = bag_c.replace('bags', '')
        bag_c = bag_c.replace('bag', '')
        bag_c = bag_c.replace('.', '')
        bag_c = map(lambda x: x.strip(), bag_c.split(', '))
    
        rules = {}
        for bag in bag_c:
            num = int(bag[0])
            rule = bag[2:]
            rules[rule] = num
    
        return {'bag': bag_p, 'rules': rules}
    
    def get_input(file_name):
        with open(file_name, 'r') as data:
            return [split_line(line[0]) for line in csv.reader(data, delimiter='|')]
    
    
    def get_bags():
        rule_set = {}
        for i in get_input('day7.txt'):
            rule_set[i['bag']] = i['rules']
    
        checked_bags = []
        bag_stack = []
        bag_count = 0
        desired_bag = 'shiny gold'
    
        def update_bag(bag_to_check):
            global bag_count
            for k in rule_set:
                inner_d = rule_set[k]
                keys = inner_d.keys()
                if bag_to_check in keys and k not in checked_bags:
                    bag_stack.append(k)
                    checked_bags.append(k)
                    bag_count += 1
    
        update_bag(desired_bag)
    
        while len(bag_stack) != 0:
            bag_d = bag_stack.pop()
            update_bag(bag_d)
    
        print(checked_bags, bag_count)
    
    get_bags()
        
                                
                            

Part 2

How many individual bags are required inside your single shiny gold bag?
Solution:
                                
                                    
    class Node(object):
        def __init__(self, nv):
            self.name = nv['name']
            self.val = nv['val']
            self.children = []
    
        def __str__(self):
            return self.name + " " + str(self.val)
    
    
    def create_node(name_val, rules):
        parent = name_val['name']
        ch = rules[name_val['name']]
        node = Node(name_val)
        if len(ch.keys()) != 0:
            node.children = [create_node({'name': k, 'val': ch[k]}, rules) for k in ch]
        return node
    
    rule_set = {}
    for i in get_input('day7.txt'):
        rule_set[i['bag']] = i['rules']
    
    tree = create_node({'name': 'shiny gold', 'val': 1}, rule_set)
    
    statement = ''
    
    def generate_statement(node):
        global statement
        if len(node.children) != 0:
            if node.name != 'shiny gold':
                statement += str(node.val)
                statement += '*'
            statement += '('
            for i in range(0, len(node.children)):
                child = node.children[i]
                generate_statement(child)
                child_statement = ''
                child_statement += str(child.val)
                if i+1 < len(node.children):
                    child_statement += '+'
                if i+1 == len(node.children):
                    child_statement += ')+'
                statement += child_statement
    
    
    generate_statement(tree)
    print(statement)
    exec('print(%s)' % statement[:-1])