|
| 1 | +import aoc |
| 2 | +from intcode import IntcodeMachine |
| 3 | +from instruction import * |
| 4 | +from day08 import blocks4, print_image4, Size |
| 5 | + |
| 6 | +from typing import List, Tuple, Set |
| 7 | +from operator import itemgetter |
| 8 | + |
| 9 | +Coord = Tuple[int] |
| 10 | + |
| 11 | +INSTRUCTIONS = { |
| 12 | + i.OPCODE : i for i in [IAdd, IMult, IHalt, IInput, IOutput, IJumpNZ, IJumpZ, ILessThan, IEquals, IAdjustOffset] |
| 13 | +} |
| 14 | + |
| 15 | +def main(): |
| 16 | + aoc.header("Space Police") |
| 17 | + |
| 18 | + program = list(map(int, aoc.get_input().readline().split(","))) |
| 19 | + aoc.output(1, run_robot, args=[program, False], post=lambda t:len(t[1])) |
| 20 | + aoc.output(2, run_robot, args=[program, True], output=part2_post) |
| 21 | + |
| 22 | + |
| 23 | +directions_clockwise = [ |
| 24 | + (0,-1), |
| 25 | + (1,0), |
| 26 | + (0,1), |
| 27 | + (-1,0) |
| 28 | +] |
| 29 | + |
| 30 | +def run_robot(prog : List[int], start_on_white): |
| 31 | + white_panels = {(0,0)} if start_on_white else set() |
| 32 | + painted_panels = set() |
| 33 | + |
| 34 | + location = (0,0) |
| 35 | + direction = directions_clockwise[0] |
| 36 | + m = IntcodeMachine(prog, INSTRUCTIONS) |
| 37 | + |
| 38 | + while m.running: |
| 39 | + try: |
| 40 | + m.input.append(1 if location in white_panels else 0) |
| 41 | + while m.step(): pass |
| 42 | + except EOFError as e: |
| 43 | + paint = m.output.pop(0) |
| 44 | + if paint == 0: |
| 45 | + white_panels -= {location} |
| 46 | + else: |
| 47 | + white_panels.add(location) |
| 48 | + |
| 49 | + painted_panels.add(location) |
| 50 | + |
| 51 | + turn = m.output.pop(0) |
| 52 | + x = 1 if turn == 1 else -1 |
| 53 | + direction = directions_clockwise[(directions_clockwise.index(direction)+x)%4] |
| 54 | + |
| 55 | + location = (location[0] + direction[0], location[1] + direction[1]) |
| 56 | + |
| 57 | + return (white_panels, painted_panels) |
| 58 | + |
| 59 | +def coords_to_img(coords : Set[Coord]): |
| 60 | + X = set(map(itemgetter(0), coords)) |
| 61 | + Y = set(map(itemgetter(1), coords)) |
| 62 | + corner_tl = ( |
| 63 | + min(X), min(Y) |
| 64 | + ) |
| 65 | + corner_br = ( |
| 66 | + max(X), max(Y) |
| 67 | + ) |
| 68 | + coords = set(map(lambda c: (c[0]-corner_tl[0], c[1]-corner_tl[1]), coords)) |
| 69 | + s = Size(corner_br[0]-corner_tl[0]+1,corner_br[1]-corner_tl[1]+1) |
| 70 | + img = [ |
| 71 | + 0 for _ in range(s.width * s.height) |
| 72 | + ] |
| 73 | + for x,y in coords: |
| 74 | + img[x + y * s.width] = 1 |
| 75 | + return img, s |
| 76 | + |
| 77 | +def part2_post(t): |
| 78 | + (white_panels, printed_panels) = t |
| 79 | + print_image4(*coords_to_img(white_panels)) |
| 80 | + |
| 81 | +if __name__ == "__main__": |
| 82 | + main() |
0 commit comments