Esempio n. 1
0
def parsed(data):
    comp = IntComputer(data)
    comp.run()
    txt = "".join([chr(x) for x in reversed(comp.output)])
    grid = ZGrid(txt)
    grid.draw()
    return grid
Esempio n. 2
0
def compute(data, input_val):
    comp = IntComputer(data, inputs=[input_val])
    comp.run()
    result, *zeros = comp.output
    for zero in zeros:
        assert zero == 0
    return result
Esempio n. 3
0
 def __init__(self):
     self.comp = IntComputer(data)
     self.world = nx.Graph()
     self.comp.input = self
     self.command_queue = deque()
     self.shortcuts = {
         "n": "north",
         "s": "south",
         "e": "east",
         "w": "west",
         "\x1b[A": "north",
         "\x1b[B": "south",
         "\x1b[C": "east",
         "\x1b[D": "west",
     }
     self.inverse = {
         "north": "south",
         "south": "north",
         "east": "west",
         "west": "east",
     }
     self.rooms = {}
     self.current_room = None
     self.prev_direction = None
     self.prev_room = None
     self.inventory = set()
     self.mode = "explore"  # or "unlock"
     self.combo = None
Esempio n. 4
0
 def __init__(self, data):
     self.grid = ZGrid({0j: "."})
     self.comp = IntComputer(data)
     self.comp.output = deque(maxlen=1)
     self.freezer = {0j: self.comp.freeze()}
     state0 = 0j
     AStar.__init__(self, state0, None)
Esempio n. 5
0
class Game:
    def __init__(self, data):
        self.cpu = IntComputer(data)
        self.cpu.input = self
        self.cpu.output = deque(maxlen=3)
        self.paddle_position = 0
        self.ball_position = 0
        self.n_blocks = 0
        self.score = 0

    def pop(self):
        p = self.paddle_position
        b = self.ball_position
        return -1 if b < p else 0 if b == p else 1

    def step(self):
        self.cpu.run(until=IntComputer.op_output)
        self.cpu.run(until=IntComputer.op_output)
        self.cpu.run(until=IntComputer.op_output)
        val, y, x = self.cpu.output
        if val == 2:
            self.n_blocks += 1
        elif val == 3:
            self.paddle_position = x
        elif val == 4:
            self.ball_position = x
        if x == -1 and y == 0:
            self.score = val

    def play(self):
        while True:
            try:
                self.step()
            except IntComputer.Halt:
                return
Esempio n. 6
0
 def __init__(self, data):
     self.cpu = IntComputer(data)
     self.cpu.input = self
     self.cpu.output = deque(maxlen=3)
     self.paddle_position = 0
     self.ball_position = 0
     self.n_blocks = 0
     self.score = 0
Esempio n. 7
0
class Q15AStar(AStar):
    def __init__(self, data):
        self.grid = ZGrid({0j: "."})
        self.comp = IntComputer(data)
        self.comp.output = deque(maxlen=1)
        self.freezer = {0j: self.comp.freeze()}
        state0 = 0j
        AStar.__init__(self, state0, None)

    def adjacent(self, z):
        self.comp.unfreeze(self.freezer[z])
        for dz, input_val in neighbours.items():
            self.comp.input.append(input_val)
            self.comp.run(until=IntComputer.op_output)
            [rc] = self.comp.output
            if rc == NACK:
                self.grid[z + dz] = "#"
            else:
                self.grid[z + dz] = "."
                self.freezer[z + dz] = self.comp.freeze()
                back = neighbours[-dz]
                self.comp.input.append(back)
                self.comp.run(until=IntComputer.op_output)
                assert self.comp.output[0]
                if rc == GOAL:
                    self.target = z + dz
                yield z + dz

    def draw(self):
        overlay = {0: "O"}
        if self.target is not None:
            overlay[self.target] = "T"
        self.grid.draw(overlay=overlay)
Esempio n. 8
0
class Robot:
    def __init__(self, data, colour0=0):
        self.brain = IntComputer(data, inputs=[colour0])
        self.brain.output = deque(maxlen=2)
        self.position = 0
        self.direction = -1j
        self.painted = {}

    def paint(self):
        while True:
            self.brain.run(until=IntComputer.op_output)
            self.brain.run(until=IntComputer.op_output)
            turn, colour = self.brain.output
            self.painted[self.position] = colour
            self.direction *= [-1j, 1j][turn]
            self.position += self.direction
            self.brain.input.append(self.painted.get(self.position, 0))

    def paint_until_halt(self):
        try:
            self.paint()
        except IntComputer.Halt:
            return
Esempio n. 9
0
def part_a(data, r1=None, r2=None):
    comp = IntComputer(data)
    if r1 is not None:
        comp.reg[1] = r1
    if r2 is not None:
        comp.reg[2] = r2
    comp.run()
    result = comp.reg[0]
    return result
Esempio n. 10
0
 def __init__(self, data, phase_settings):
     self.comps = [
         IntComputer(data, inputs=[val]) for val in phase_settings
     ]
     for left, right in zip(self.comps, self.comps[1:] + [self.comps[0]]):
         left.output = right.input
Esempio n. 11
0
            for C in C_choices:
                compressed_pathABC = compressed_pathAB
                pathABC = pathAB
                while pathABC.startswith((A, B, C)):
                    if pathABC.startswith(A):
                        pathABC = pathABC[len(A):].lstrip(",")
                        compressed_pathABC += "A,"
                    if pathABC.startswith(B):
                        pathABC = pathABC[len(B):].lstrip(",")
                        compressed_pathABC += "B,"
                    if pathABC.startswith(C):
                        pathABC = pathABC[len(C):].lstrip(",")
                        compressed_pathABC += "C,"
                if not pathABC:
                    result = compressed_pathABC.rstrip(",")
                    if len(result) <= mem:
                        results.append("\n".join([result, A, B, C]))
    return results


if __name__ == "__main__":
    grid = parsed(data)
    print("part a", calibration(grid))

    comp = IntComputer(data)
    comp.reg[0] = 2
    path = get_path(grid)
    comp.input_text(path)
    comp.run()
    print("part b", comp.output[0])
Esempio n. 12
0
def beam(z):
    comp = IntComputer(data, inputs=[int(z.imag), int(z.real)])
    comp.run(until=IntComputer.op_output)
    [result] = comp.output
    return result
def test_intcode_samples(data, output):
    comp = IntComputer(data)
    comp.run()
    assert ",".join([str(v) for v in comp.reg.values()]) == output
Esempio n. 14
0
WALK
"""

# Jump if (there's a hole 1 space away (not A)
#       or there's a hole 2 spaces away (not B)
#       or there's a hole 3 spaces away (not C))
# and there's ground 4 spaces away (NOT NOT D)
# and (there's ground 8 spaces away (H)
#      or 5 spaces away (E))
prog_b = """\
NOT A J
NOT B T
OR T J
NOT C T
OR T J
NOT D T
NOT T T
AND T J
AND H T
OR E T
AND T J
RUN
"""

for part, prog in zip("ab", [prog_a, prog_b]):
    comp = IntComputer(data, inputs=[ord(x) for x in reversed(prog)])
    comp.run()
    val = comp.output.popleft()
    print(*[chr(x) for x in reversed(comp.output)], sep="")
    print("part", part, val)
Esempio n. 15
0
class Game:
    def __init__(self):
        self.comp = IntComputer(data)
        self.world = nx.Graph()
        self.comp.input = self
        self.command_queue = deque()
        self.shortcuts = {
            "n": "north",
            "s": "south",
            "e": "east",
            "w": "west",
            "\x1b[A": "north",
            "\x1b[B": "south",
            "\x1b[C": "east",
            "\x1b[D": "west",
        }
        self.inverse = {
            "north": "south",
            "south": "north",
            "east": "west",
            "west": "east",
        }
        self.rooms = {}
        self.current_room = None
        self.prev_direction = None
        self.prev_room = None
        self.inventory = set()
        self.mode = "explore"  # or "unlock"
        self.combo = None

    def find_path(self, to=None):
        last_step = None
        if to is None:
            # just go to any unexplored room...
            for room in self.rooms.values():
                if room.name == "Security Checkpoint":
                    continue
                if any(v is None for v in room.doors.values()):
                    to = room
                    last_step = next(k for k, v in room.doors.items()
                                     if v is None)
                    break
            else:
                return
        intermediate_rooms = nx.shortest_path(self.world, self.current_room,
                                              to)
        path = []
        for left, right in zip(intermediate_rooms, intermediate_rooms[1:]):
            direction = next(d for d, r in left.doors.items() if r is right)
            path.append(direction)
        if last_step is not None:
            path.append(last_step)
        if not path:
            # can happen if you try to find path to room but you're already there
            return
        first_step = path[0]
        return first_step

    @cached_property
    def combos(self):
        data = {}
        inventory = sorted(self.inventory)
        for i in range(len(inventory)):
            for combo in combinations(inventory, i):
                data[combo] = "new"
        return data

    @cached_property
    def unlock_direction(self):
        return next(k for k, v in self.current_room.doors.items() if v is None)

    def pop(self):
        if not self.command_queue:
            # command queue is exhausted, need to update status and find task to do
            command = ""
            output = self.comp.output_as_text

            # entered a room
            if output.strip().startswith("=="):
                parsed_room = parse_room(output)
                here = parsed_room["name"]
                if here == "Pressure-Sensitive Floor":
                    if "ejected" in output:
                        if "Droids on this ship are heavier" in output:
                            self.combos[self.combo] = "too light"
                            self.combo = None
                        elif "Droids on this ship are lighter" in output:
                            self.combos[self.combo] = "too heavy"
                            self.combo = None
                        else:
                            log.warning("shouldn't be here: %r", output)
                log.debug("parsed room data: %s", parsed_room)
                if here not in self.rooms:
                    log.debug("entered new room %r, adding to graph",
                              parsed_room)
                    new_room = self.rooms[here] = Room(**parsed_room)
                    if self.prev_room is not None:
                        back = self.inverse[self.prev_direction]
                        self.world.add_edge(
                            new_room,
                            self.prev_room,
                            **{
                                self.prev_direction: new_room,
                                back: self.prev_room
                            },
                        )
                        new_room.doors[back] = self.prev_room
                        self.prev_room.doors[self.prev_direction] = new_room
                    else:
                        self.world.add_node(new_room)

                self.current_room = self.rooms[here]
                if here == "Pressure-Sensitive Floor":
                    if "ejected" in output:
                        # actually we got kicked out
                        self.current_room = self.rooms["Security Checkpoint"]

            # update inventory of self and rooms
            for line in output.splitlines():
                if line.startswith("You take the "):
                    item = line[13:-1]
                    self.current_room.items.remove(item)
                    self.inventory.add(item)
                if line.startswith("You drop the "):
                    item = line[13:-1]
                    self.inventory.remove(item)
                    self.current_room.items.append(item)

            # echo on
            self.comp.output.clear()
            print(output, end="", flush=True)

            # pick up any crap we find lying around
            if self.mode == "explore":
                for item in self.current_room.items:
                    if item not in blacklist:
                        log.info("autotaking %r", item)
                        command += f"take {item}\n"

            # there was nothing to take, explore around the ship
            if self.mode == "explore" and not command:
                step = self.find_path()
                if step is not None:
                    command = step
                else:
                    # we've explored everything, proceed to checkpoint
                    self.mode = "unlock"
                    command = self.find_path(
                        to=self.rooms["Security Checkpoint"])
                if command is None:
                    command = "inv"
                else:
                    self.prev_direction = command
                    self.prev_room = self.current_room
                log.info("entering command %r", command)

            # continue proceeding to checkpoint
            if self.mode == "unlock":
                if self.current_room.name != "Security Checkpoint":
                    command = self.find_path(
                        to=self.rooms["Security Checkpoint"])
                    self.prev_direction = command
                    self.prev_room = self.current_room

            if self.mode == "unlock" and not command:
                assert self.current_room.name == "Security Checkpoint"
                if self.combo is None:
                    self.combo = next(k for k, v in self.combos.items()
                                      if v == "new")
                combo = set(self.combo)
                diff = combo ^ self.inventory
                for item in diff:
                    if item in self.inventory:
                        command = f"drop {item}"
                    else:
                        assert item in combo and item not in self.inventory
                        command = f"take {item}"
                    break
                else:
                    assert combo == self.inventory
                    log.info("trying combo %s", combo)
                    command = self.unlock_direction

            # don't know what to do
            if not command:
                # interactive fallback
                command = input()

            if not command:
                # so that pressing "enter" at the prompt adds some useful context
                if self.world:
                    # soft dependency on https://github.com/cosminbasca/asciinet
                    try:
                        from asciinet import graph_to_ascii

                        print(graph_to_ascii(self.world))
                    except Exception as err:
                        log.warning("Couldn't graph the space: %r", err)
                print("current room:", self.current_room.name)
                print(self.current_room.description)
                print("doors:", "/".join(self.current_room.doors))
                print("inventory:", ", ".join(sorted(self.inventory)))

            # a convenience shortcut to take the item here
            if command == "t" and len(self.current_room.items) == 1:
                [item] = self.current_room.items
                command = f"take {item}"

            # allows to use the arrow keys or enter just "n" instead of typing "north"
            command = self.shortcuts.get(command, command)
            if not command.endswith("\n"):
                command += "\n"

            for char in command:
                self.command_queue.appendleft(ord(char))

        return self.command_queue.pop()

    def play(self):
        self.comp.run()
        txt = self.comp.output_as_text
        if "Analysis complete! You may proceed." not in txt:
            log.warning("should be done but: %r", txt)
            raise Exception
        [code] = [word for word in txt.split() if word.isdigit()]
        print("part a", code)
Esempio n. 16
0
 def __init__(self, data, colour0=0):
     self.brain = IntComputer(data, inputs=[colour0])
     self.brain.output = deque(maxlen=2)
     self.position = 0
     self.direction = -1j
     self.painted = {}
Esempio n. 17
0
def compute(data, inputs=()):
    comp = IntComputer(data, inputs=inputs)
    comp.run()
    result = ",".join([str(x) for x in reversed(comp.output)])
    return result
Esempio n. 18
0
 def __init__(self, data):
     self.y0 = set()
     self.xy = None, None
     self.comps = [IntComputer(data, inputs=[i]) for i in range(50)]
     self.done = False