Advent of Code: Day 18

For Day 18, we have another challenge that involves implementing a parser. My Python solution is:

import time
import Queue
from itertools import cycle
with open("input.txt", "r") as o:
    commands = o.read().split("\n")


class Program():
    def __init__(self, id, commands, in_queue, out_queue):
        self.id = id
        self.registers = {"p": self.id}
        self.ptr = 0
        self.commands = commands
        self.in_queue = in_queue
        self.out_queue = out_queue
        self.total_sent = 0
        self.blocked = False

    def get_value(self, f):
        try:
            return int(f)
        except ValueError:
            return self.registers.get(f, 0)

    def run(self):
        self.blocked = False
        while True:
            cmd = self.commands[self.ptr].split(" ")
            self.ptr += 1
            if cmd[0] == "set":
                self.registers[cmd[1]] = self.get_value(cmd[2])
            elif cmd[0] == "add":
                self.registers[cmd[1]] = self.get_value(cmd[1]) + self.get_value(cmd[2])
            elif cmd[0] == "mul":
                self.registers[cmd[1]] = self.get_value(cmd[1]) * self.get_value(cmd[2])
            elif cmd[0] == "mod":
                self.registers[cmd[1]] = self.get_value(cmd[1]) % self.get_value(cmd[2])
            elif cmd[0] == "snd":
                self.total_sent += 1
                self.out_queue.put(self.get_value(cmd[1]))
            elif cmd[0] == "rcv":
                if self.in_queue.empty():
                    self.ptr -= 1
                    self.blocked = True
                    return
                self.registers[cmd[1]] = self.in_queue.get()
            elif cmd[0] == "jgz":
                if self.get_value(cmd[1]) > 0:
                    self.ptr += self.get_value(cmd[2]) - 1

in_queue = Queue.Queue()
out_queue = Queue.Queue()
part1 = Program(0, commands, in_queue, out_queue)

while True:
    part1.run()
    while out_queue.qsize() > 1:
        out_queue.get()
    p = out_queue.get()
    if not p == 0:
        print "Part 1", p
        break
    in_queue.put(p)

queue1 = Queue.Queue()
queue2 = Queue.Queue()

p0 = Program(0, commands, queue1, queue2)
p1 = Program(1, commands, queue2, queue1)

for p in cycle([p0, p1]):
    p.run()
    if p0.blocked and p1.blocked and queue1.qsize() + queue2.qsize() == 0:
        break
print "Part 2", p1.total_sent

Part 1 has been hacked up a bit to fit the structure of Part 2 - as it needs to treat the send and receive statements as storage of a single variable rather than interacting with a queue.

Advent of Code runs every day up to Christmas, you should join in!.

Show Comments

Get the latest posts delivered right to your inbox.