Ejemplo n.º 1
0
def main():
    with open("day13.txt", "r") as fp:
        memory = dict()
        for i, s in enumerate(fp.read().split(",")):
            memory[i] = int(s)

    # Part 1
    screen = defaultdict(lambda: 0)
    output = run_program(defaultdict(lambda: 0, memory), iter([]))
    try:
        while True:
            x, y, v = next(output), next(output), next(output)
            screen[(x, y)] = v
    except StopIteration:
        pass
    count = 0
    for v in screen.values():
        if v == 2:
            count += 1
    print(count)

    # Part 2
    screen = defaultdict(lambda: 0)
    start_memory = defaultdict(lambda: 0, memory)
    start_memory[0] = 2

    def input2():
        while True:
            ball = None
            paddle = None
            for k, v in screen.items():
                if v == 3:
                    paddle = k
                elif v == 4:
                    ball = k
            if paddle[0] < ball[0]:
                yield 1
            elif paddle[0] > ball[0]:
                yield -1
            else:
                yield 0

    output = run_program(start_memory, input2())
    try:
        while True:
            x, y, v = next(output), next(output), next(output)
            screen[(x, y)] = v
    except StopIteration:
        pass
    print(screen[(-1, 0)])
Ejemplo n.º 2
0
def run_ascii(memory, input):
    output_iter = run_program(defaultdict(lambda: 0, memory),
                              (ord(c) for c in input))
    for c in output_iter:
        if c > 128:
            print(c)
        elif chr(c) == "\n":
            print()
        else:
            print(chr(c), end="")
Ejemplo n.º 3
0
def run_robot(memory, start_panels):
    panels = defaultdict(lambda: 0, start_panels)
    directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]
    direction = 0
    position = (0, 0)

    def input1():
        while True:
            yield panels[position]

    execution = run_program(defaultdict(lambda: 0, memory), input1())
    try:
        while True:
            color = next(execution)
            rotation = next(execution)
            panels[position] = color
            direction = (direction +
                         (1 if rotation == 1 else -1)) % len(directions)
            position = (position[0] + directions[direction][0],
                        position[1] + directions[direction][1])
    except StopIteration:
        pass
    return panels
Ejemplo n.º 4
0
def main():
    with open("day25.txt", "r") as fp:
        memory = dict()
        for i, s in enumerate(fp.read().split(",")):
            memory[i] = int(s)

    # Part 1
    #
    #                               Stables -- Crew Quarters - Engineering - Corridor
    #                                                |      SCP - Arcade                 Sick Bay
    #                                                |                                   Kitchen ------ Hallway
    #           Storage --- Passages -- GWC --- Science Lab -- Holodeck ---- Warp Drive Maintenance
    #                Hot Chocolate Fountain                   Hull Breach
    #
    #
    # Holodeck: giant electromagnet (don't take this)
    # Warp Drive Maintenance: ornament
    # Kitchen: escape pod (leaves the ship)
    # Sick Bay: dark matter
    # Crew Quarters: astrolabe
    # Engineering: hologram
    # Corridor: klein bottle
    # Arcade: molten lava (don't take this)
    # GWC: candy cane
    # Passages: photons (don't take this)
    # Storage: tambourine
    last_output = "Command?"

    def brute_force_checkput(dir, items):
        for item in items:
            yield "drop " + item
        for i in range(2**len(items)):
            for bit in range(len(items)):
                if i & (1 << bit):
                    yield "take " + items[bit]
            yield dir
            if "Alert!" not in last_output:
                break
            for bit in range(len(items)):
                if i & (1 << bit):
                    yield "drop " + items[bit]
        print("NO SOLUTION FOUND!")

    def input1():
        # First take all the items in the lower half of the ship
        take_all_items = "\n".join([
            "north",
            "east",
            "take ornament",
            "north",
            "north",
            "take dark matter",
            "south",
            "south",
            "west",
            "west",
            "west",
            "take candy cane",
            "west",
            "west",
            "take tambourine",
            "east",
            "east",
            "east",
            "north",
            "take astrolabe",
            "east",
            "take hologram",
            "east",
            "take klein bottle",
            "west",
            "south",
            "west",
        ]) + "\n"
        for c in take_all_items:
            yield ord(c)
        items = [
            "ornament", "dark matter", "candy cane", "tambourine", "astrolabe",
            "hologram", "klein bottle"
        ]

        # Try to pass the first Security Checkpoint (SCP)
        for command in brute_force_checkput("north", items):
            for c in command:
                yield ord(c)
            yield (ord("\n"))

        while True:
            line = input()
            line = line.strip() + "\n"
            for c in line:
                yield ord(c)

    for c in run_program(defaultdict(lambda: 0, memory), input1()):
        if chr(c) == "\n":
            print()
        else:
            print(chr(c), end="")
        last_output += chr(c)
        if last_output.endswith("Command?"):
            last_output = last_output[last_output.index("Command?") + 8:]
Ejemplo n.º 5
0
def main():
    with open("day23.txt", "r") as fp:
        memory = dict()
        for i, s in enumerate(fp.read().split(",")):
            memory[i] = int(s)
    
    # Part 1
    receive_queues = [Queue() for i in range(50)]
    done_queue = Queue()
    def receive(index):
        yield index
        while True:
            try:
                (x, y) = receive_queues[index].get_nowait()
                yield x
                yield y
            except Empty:
                yield -1
                yield -1
    def send(index, program):
        while True:
            dest = next(program)
            x = next(program)
            y = next(program)
            if dest == 255:
                done_queue.put_nowait(y)
                break
            receive_queues[dest].put_nowait((x, y))
    
    senders = [
        Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i))))
        for i
        in range(50)
    ]
    for sender in senders:
        sender.start()
    result = done_queue.get()
    for sender in senders:
        sender.terminate()
    print(result)

    # Part 2
    receive_queues = [Queue() for i in range(50)]
    nat_value = Array(ctypes.c_long, 2)
    waiting = Array(ctypes.c_bool, len(receive_queues))
    def receive(index):
        yield index
        while True:
            try:
                (x, y) = receive_queues[index].get_nowait()
                with waiting.get_lock():
                    waiting[index] = False
                yield x
                yield y
            except Empty:
                with waiting.get_lock():
                    waiting[index] = True
                yield -1
                yield -1
    def send(index, program):
        while True:
            dest = next(program)
            x = next(program)
            y = next(program)
            if dest == 255:
                with nat_value.get_lock():
                    nat_value[0] = x
                    nat_value[1] = y
            else:
                receive_queues[dest].put_nowait((x, y))
    
    senders = [
        Process(target=send, args=(i, run_program(defaultdict(lambda: 0, memory), receive(i))))
        for i
        in range(50)
    ]
    for sender in senders:
        sender.start()
    
    last_nat_y = None
    while True:
        sleep(0.25)
        with waiting.get_lock():
            all_waiting = True
            for w in waiting:
                all_waiting = all_waiting and waiting
            if all_waiting:
                with nat_value.get_lock():
                    receive_queues[0].put_nowait((nat_value[0], nat_value[1]))
                    if last_nat_y == nat_value[1]:
                        break
                    else:
                        last_nat_y = nat_value[1]
    for sender in senders:
        sender.terminate()
    print(last_nat_y)
Ejemplo n.º 6
0
 def has_beam(x, y):
     return next(run_program(defaultdict(lambda: 0, memory),
                             iter([x, y]))) == 1
Ejemplo n.º 7
0
def main():
    with open("day17.txt", "r") as fp:
        memory = dict()
        for i, s in enumerate(fp.read().split(",")):
            memory[i] = int(s)

    # Part 1
    map = [[]]
    for c in run_program(defaultdict(lambda: 0, memory), iter([])):
        c = chr(c)
        if c == "\n":
            map.append([])
        else:
            map[-1].append(c)
    while map[-1] == []:
        del map[-1]
    for y in range(len(map)):
        for x in range(len(map[y])):
            print(map[y][x], end="")
        print()
    result = 0
    for y in range(1, len(map) - 1):
        for x in range(1, len(map[0]) - 1):
            if map[y][x] == "#" and map[y - 1][x] == "#" and map[
                    y + 1][x] == "#" and map[y][x +
                                                1] == "#" and map[y][x -
                                                                     1] == "#":
                result += x * y
    print(result)

    # Part 2
    def map_get(x, y):
        if 0 <= y and y < len(map) and 0 <= x and x < len(map[y]):
            return map[y][x]
        else:
            return "."

    # Find the robot
    rx, ry = -1, -1
    dx, dy = -1, -1
    for y in range(len(map)):
        for x in range(len(map[y])):
            if map[y][x] == "<":
                dx, dy = -1, 0
                rx, ry = x, y
            elif map[y][x] == "^":
                dx, dy = 0, -1
                rx, ry = x, y
            elif map[y][x] == ">":
                dx, dy = 1, 0
                rx, ry = x, y
            elif map[y][x] == "v":
                dx, dy = 0, 1
                rx, ry = x, y

    # Follow the path
    commands = []
    while True:
        # Go ahead
        commands.append(0)
        while map_get(rx + dx, ry + dy) == "#":
            commands[-1] += 1
            rx, ry = rx + dx, ry + dy
        if commands[-1] == 0:
            del commands[-1]

        # Check for a turn
        if map_get(rx + dy, ry - dx) == "#":
            commands.append("L")
            dx, dy = dy, -dx
        elif map_get(rx - dy, ry + dx) == "#":
            commands.append("R")
            dx, dy = -dy, dx
        else:
            break
    commands = [str(command) for command in commands]

    def possible_subprograms():
        for start in range(len(commands)):
            for slen in range(1, len(commands) - start + 1):
                prog = ",".join(commands[start:start + slen])
                if len(prog) <= 20:
                    yield prog

    possible_subprograms = set(possible_subprograms())

    commands_str = ",".join(commands)
    found = False
    for a in possible_subprograms:
        for b in possible_subprograms:
            for c in possible_subprograms:
                prog_str = commands_str.replace(a, "A").replace(b,
                                                                "B").replace(
                                                                    c, "C")
                if len(prog_str) <= 20 and PATTERN.match(prog_str):
                    found = True
                    break
            if found:
                break
        if found:
            break
    print(prog_str, a, b, c)

    def program_input():
        prog = (
            prog_str + "\n" +  # main
            a + "\n" +  # A
            b + "\n" +  # B
            c + "\n" +  # C
            "n\n"  # feed
        )
        for ch in prog:
            yield (ord(ch))

    program_memory = defaultdict(lambda: 0, memory)
    program_memory[0] = 2
    program_output = run_program(program_memory, program_input())
    for po in program_output:
        if po > 128:
            print(po)
        else:
            pass
Ejemplo n.º 8
0
def main():
    with open("day15.txt", "r") as fp:
        memory = dict()
        for i, s in enumerate(fp.read().split(",")):
            memory[i] = int(s)

    # Part 1
    #########
    map = defaultdict(lambda: " ")
    pos = (0, 0)
    map[pos] = "."
    input_queue = []
    robot = run_program(defaultdict(lambda: 0, memory),
                        read_input_queue(input_queue))

    # 1. move up until we hit a wall
    input_queue.append(NORTH)
    output = next(robot)
    pos = handle_output(map, pos, input_queue[-1], output)

    # 2. follow the wall
    start_pos = pos
    wall_dir = NORTH
    while True:
        input_queue.append(wall_dir)
        output = next(robot)
        pos = handle_output(map, pos, input_queue[-1], output)
        if output != WALL:
            wall_dir = CCW_OF[wall_dir]
        else:
            input_queue.append(CW_OF[wall_dir])
            output = next(robot)
            pos = handle_output(map, pos, input_queue[-1], output)
            if output == WALL:
                wall_dir = input_queue[-1]
        if pos == start_pos and wall_dir == NORTH:
            break
    print_map(map)

    # 3. DFS
    done = set()
    frontier = set([(0, 0)])
    iteration = 0
    oxygen_pos = None
    while True:
        for pos in frontier:
            if map[pos] == "x":
                oxygen_pos = pos
                break
        if oxygen_pos:
            break
        iteration += 1
        new_frontier = set()
        for pos in frontier:
            new_frontier.update(
                offset(pos, off) for off in OFFSET_OF.values() if
                map[offset(pos, off)] != "#" and offset(pos, off) not in done)
        done.update(frontier)
        frontier = new_frontier
    print(iteration)

    # Part 2
    #########
    # Again just use a DFS
    done = set()
    frontier = set([oxygen_pos])
    iteration = 0
    while len(frontier) > 0:
        iteration += 1
        new_frontier = set()
        for pos in frontier:
            new_frontier.update(
                offset(pos, off) for off in OFFSET_OF.values() if
                map[offset(pos, off)] != "#" and offset(pos, off) not in done)
        done.update(frontier)
        frontier = new_frontier
    print(iteration - 1)
Ejemplo n.º 9
0
def test_large_number():
    program = "104,1125899906842624,99"
    assert run_program(program) == [1125899906842624]
Ejemplo n.º 10
0
def test_sixteen_digit():
    program = "1102,34915192,34915192,7,4,7,99,0"
    assert run_program(program) == [1219070632396864]
Ejemplo n.º 11
0
def test_returns_self():
    program = "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99"
    expected_output = [int(a) for a in program.split(',')]
    assert run_program(program) == expected_output