DEV Community

Cover image for Advent of Code 2023 - December 20th
Rob van der Leek
Rob van der Leek

Posted on

Advent of Code 2023 - December 20th

In this series, I'll share my progress with the 2023 version of Advent of Code.

Check the first post for a short intro to this series.

You can also follow my progress on GitHub.

December 20th

The puzzle of day 20 needed a lot of code (at least for the solution I chose.) I enjoyed part one but was lost for part two (brute-force is not going to cut it.) A post on Reddit gave me a push in the right direction.

My pitfall for this puzzle: I totally underestimated part two and was expecting my solution for part one would also work for part two (it did not.)

Solution here, do not click if you want to solve the puzzle first yourself
#!/usr/bin/env python3

class Broadcaster:
    def __init__(self, destinations):
        self._destinations = destinations

    def process(self, name_from, pulse, stack):
        for d in self._destinations:
            stack.append('broadcaster', d, pulse) 

class Conjunction:
    def __init__(self, name, destinations):
        self._name = name
        self._destinations = destinations
        self._memory = {}

    def add_input(self, name):
        self._memory[name] = 'low'

    def process(self, name_from, pulse, stack):
        self._memory[name_from] = pulse
        if not 'low' in self._memory.values():
            for d in self._destinations:
                stack.append(self._name, d, 'low') 
            return 'low'        
        else:
            for d in self._destinations:
                stack.append(self._name, d, 'high') 
            return 'high'

class FlipFlop:
    def __init__(self, name, destinations):
        self._name = name
        self._destinations = destinations
        self._memory = 'low' 

    def add_input(self, name):
        pass

    def process(self, name_from, pulse, stack):
        if pulse == 'low':
            self._memory = 'high' if self._memory == 'low' else 'low'
            for d in self._destinations:
                stack.append(self._name, d, self._memory)

with open('input.txt') as infile:
    lines = infile.readlines()
modules = {}
for line in lines:
    parts = line.strip().split(' -> ')
    operation = parts[0]
    operands = parts[1].split(', ')
    if operation == 'broadcaster':
        modules['broadcaster'] = Broadcaster(operands)
    elif operation.startswith('&'):
        modules[operation[1:]] = Conjunction(operation[1:], operands) 
    elif operation.startswith('%'):
        modules[operation[1:]] = FlipFlop(operation[1:], operands) 

for line in lines:
    parts = line.strip().split(' -> ')
    operation = parts[0]
    operands = parts[1].split(', ')
    if operation != 'broadcaster':
        for operand in operands:
            if operand in modules:
                modules[operand].add_input(operation[1:])

class Stack:
    def __init__(self):
        self._stack = [] 
        self.count = {'low': 0, 'high': 0}

    def append(self, name_from, name_to, pulse):
        self.count[pulse] += 1
        self._stack.append((name_from, name_to, pulse))

    def next(self):
        return self._stack.pop(0)

    def is_empty(self):
        return len(self._stack) == 0

stack = Stack()
iterations = {}
for i in range(10000):
    stack.append('button', 'broadcaster', 'low')
    while not stack.is_empty():
        [name_from, name_to, pulse] = stack.next()
        if name_to in modules:
            result = modules[name_to].process(name_from, pulse, stack)
            if name_to in ['nx', 'sp', 'cc', 'jq'] and \
                name_to not in iterations and result == 'high':
                iterations[name_to] = i + 1
    if 'nx' in iterations and 'sp' in iterations and 'cc' in iterations \
        and 'jq' in iterations:  
            break

print(stack.count['low'] * stack.count['high'])
print(iterations['nx'] * iterations['sp'] * iterations['cc'] * iterations['jq'])
Enter fullscreen mode Exit fullscreen mode

That's it! See you again tomorrow!

Top comments (0)