from collections import deque

from vm import VM, read_program

ns = read_program(21)


def run(inputs):
    for output in VM(ns, deque(map(ord, inputs))):
        pass
    return output


# Part one
# We want to jump if there is land in four steps, but a hole
# in one of the next three steps, i.e.
#   J = D AND ((NOT A) OR (NOT B) OR (NOT C))
inputs = """NOT A T
NOT B J
OR T J
NOT C T
OR T J
AND D J
WALK
"""
print(run(inputs))

# Part two
# We now want to also ensure that there is land at either
# 5 steps or 8 steps, i.e. something like
#    J = D AND ((NOT A) OR (NOT B) OR (NOT C)) AND (H OR E)
Exemple #2
0
from collections import deque
from itertools import cycle, permutations
from math import inf

from vm import VM, read_program

p07 = read_program(7)

# Part one
m = -inf
for perm in permutations(range(5)):
    vms = []
    signal = 0
    for phase in perm:
        vm = VM(p07)
        signal = next(VM(p07, deque([phase, signal])))
    m = max(m, signal)
print(m)

# Part two
m = -inf
for perm in permutations(range(5, 10)):
    vms = [VM(p07, deque([phase])) for phase in perm]
    signal = 0
    try:
        for i in cycle(range(5)):
            vms[i].inputs.append(signal)
            signal = next(vms[i])
    except StopIteration:
        m = max(m, signal)
print(m)
from collections import deque

import networkx as nx

from vm import VM, read_program

ns = read_program(15)

q = deque()
vm = VM(ns)
q.append((0, vm))
direction = {1: 1j, 2: -1j, 3: -1, 4: 1}
G = nx.Graph()

while q:
    loc, base_vm = q.pop()
    for d in range(1, 5):
        vm = base_vm.clone()
        vm.inputs = deque([d])
        output = next(vm)
        if output:
            new_loc = loc + direction[d]
            if new_loc not in G.nodes:
                if output == 2:
                    oxygen = new_loc
                q.append((new_loc, vm))
                G.add_edge(loc, new_loc)

# Part one
print(nx.shortest_path_length(G, 0, oxygen))
Exemple #4
0
from collections import deque

from vm import VM, read_program

p05 = read_program(5)

# Part one
vm = VM(p05, deque([1]))
print(vm.run_until_next_nonzero_output())

# Part two
vm = VM(p05, deque([5]))
print(next(vm))
from collections import deque
from itertools import chain, combinations
import sys

from vm import VM, read_program

ns = read_program(25)

# We first play the actual game to figure out what items exist and where
# the locked door is; to play the game, run `python -m day25.solutions -i`
if len(sys.argv) > 1 and sys.argv[1] == '-i':
    inputs = deque([])
    vm = VM(ns, inputs)
    while True:
        o = next(vm.it)
        if o is not None:
            print(chr(o), end='')
        elif not inputs:
            inp = input() + '\n'
            for c in map(ord, inp):
                inputs.append(c)


# Now, loop over all possible combinations of items to drop. If we are neither
# too heavy or too light, that means we're done.
def powerset(iterable):
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))


items = ['spool of cat6', 'asterisk', 'jam', 'shell', 'astronaut ice cream', 'space heater',
Exemple #6
0
from collections import defaultdict, deque

from vm import VM, read_program

ns = read_program(11)


def get_colors(initial):
    inputs = deque()
    vm = VM(ns, inputs)
    d = -1j
    loc = 0
    colors = defaultdict(int)
    colors[0] = initial
    try:
        while True:
            inputs.append(colors[loc])
            colors[loc] = next(vm)
            d *= 1j if next(vm) else -1j
            loc += d
    except StopIteration:
        return colors


# Part one
print(len(get_colors(0)))

# Part two
c = get_colors(1)
reals = set(int(z.real) for z in c)
imags = set(int(z.imag) for z in c)
Exemple #7
0
from collections import defaultdict, deque
from queue import Queue
import time
from vm import VM, read_program

ns = read_program(23)


class Input:
    def __init__(self, i):
        self.inputs = deque([i])

    def popleft(self):
        return self.inputs.popleft() if self.inputs else -1

    def add(self, val):
        self.inputs.append(val)


vms = []
for i in range(50):
    inputs = Input(i)
    vm = VM(ns, inputs)
    vms.append(vm)
i = 0
idling = set()
NAT = None
last_y = None
while True:
    dst = next(vms[i].it)
    if dst is None:
Exemple #8
0
from collections import deque
from itertools import count

from vm import VM, read_program

ns = read_program(19)

# Part one
print(sum(next(VM(ns, deque([x, y]))) for x in range(50) for y in range(50)))


# A quick glance at the output suggest that the relevant y coordinate
# is at least 500, so we start our search there to avoid some edge
# cases near the origin
def solve():
    prev_first_x = 0
    rows = []
    for y in count(500):
        first_x = None
        if prev_first_x == None:
            prev_first_x = 0
        x = prev_first_x
        while True:
            inputs = deque([x, y])
            vm = VM(ns, inputs)
            output = next(vm)
            if output:
                if first_x == None:
                    first_x = x
                    if rows:
                        x = rows[-1][1] - 1
from collections import deque

from vm import VM, read_program

p09 = read_program(9)

# Part one
vm = VM(p09, deque([1]))
print(next(vm))

# Part two
vm = VM(p09, deque([2]))
print(next(vm))
import numpy as np

from vm import VM, read_program

ns = read_program(13)

# Part one
vm = VM(ns)
print(sum(t == 2 for _, _, t in zip(vm, vm, vm)))

# Part two
paddle_x = 0
ball_x = 0


class AI:
    @staticmethod
    def popleft():
        return np.sign(ball_x - paddle_x)


vm = VM(ns, AI)
vm[0] = 2
try:
    while True:
        x, y, tile_id = next(vm), next(vm), next(vm)
        if x == -1 and y == 0:
            score = tile_id
        elif tile_id == 3:
            paddle_x = x
        elif tile_id == 4:
Exemple #11
0
from collections import deque

from vm import VM, read_program

ns = read_program(17)

# Part one
vm = VM(ns)
x = 0
y = 0
scaffolds = set()
field = {}
for output in vm:
    field[y + x * 1j] = output
    if output == 35:
        scaffolds.add(y + x * 1j)
    if output == 10:
        y += 1
        x = 0
    else:
        x += 1

print(
    sum(x.real * x.imag for x in scaffolds if x + 1 in scaffolds and x -
        1 in scaffolds and x + 1j in scaffolds and x - 1j in scaffolds))

# Part two
# We first take a look at the map and based on that, manually
# determine what the routines must look like.
max_x = int(max(z.real for z in scaffolds))
max_y = int(max(z.imag for z in scaffolds))