Day 11
This commit is contained in:
parent
8a74fb8ee7
commit
9ee5858d04
88
2019/day11.py
Normal file
88
2019/day11.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
from queue import Queue
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from intcode import Intcode
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
with open("day11.txt", "rt") as input_file:
|
||||||
|
text = input_file.readlines()[0].rstrip()
|
||||||
|
codes = Intcode.parse_input(text)
|
||||||
|
|
||||||
|
# Part 1
|
||||||
|
robot = Robot(codes)
|
||||||
|
robot.run()
|
||||||
|
print("Num painted:", robot.get_num_painted())
|
||||||
|
|
||||||
|
# Part 2
|
||||||
|
robot = Robot(codes, draw=True)
|
||||||
|
robot.set_paint(1)
|
||||||
|
robot.run()
|
||||||
|
robot.save_image("/tmp/day11.png")
|
||||||
|
|
||||||
|
|
||||||
|
class Robot(Intcode):
|
||||||
|
|
||||||
|
OP_PAINT = 0
|
||||||
|
OP_TURN = 1
|
||||||
|
|
||||||
|
UP = 0
|
||||||
|
RIGHT = 1
|
||||||
|
DOWN = 2
|
||||||
|
LEFT = 3
|
||||||
|
|
||||||
|
def __init__(self, codes, debug=False, draw=False):
|
||||||
|
super().__init__(codes, debug=debug)
|
||||||
|
self.panel = {}
|
||||||
|
self.x = 0
|
||||||
|
self.y = 0
|
||||||
|
self.direction = self.UP
|
||||||
|
self.output_type = self.OP_PAINT
|
||||||
|
self.image = Image.new("1", (100, 100)) if draw else None
|
||||||
|
|
||||||
|
def input_data(self):
|
||||||
|
return self.get_paint()
|
||||||
|
|
||||||
|
def output_data(self, data):
|
||||||
|
if self.output_type == self.OP_PAINT:
|
||||||
|
self.set_paint(data)
|
||||||
|
self.output_type = self.OP_TURN
|
||||||
|
elif self.output_type == self.OP_TURN:
|
||||||
|
self.direction += 1 if data == 1 else -1
|
||||||
|
self.move()
|
||||||
|
self.output_type = self.OP_PAINT
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
self.x, self.y = {
|
||||||
|
self.UP: (self.x + 1, self.y),
|
||||||
|
self.RIGHT: (self.x, self.y + 1),
|
||||||
|
self.DOWN: (self.x - 1, self.y),
|
||||||
|
self.LEFT: (self.x, self.y - 1),
|
||||||
|
}[self.get_direction()]
|
||||||
|
|
||||||
|
def get_direction(self):
|
||||||
|
return self.direction % 4
|
||||||
|
|
||||||
|
def get_paint(self):
|
||||||
|
if self.x not in self.panel or self.y not in self.panel[self.x]:
|
||||||
|
self.set_paint(0)
|
||||||
|
return self.panel[self.x][self.y]
|
||||||
|
|
||||||
|
def set_paint(self, color):
|
||||||
|
if self.x not in self.panel:
|
||||||
|
self.panel[self.x] = {}
|
||||||
|
self.panel[self.x][self.y] = color
|
||||||
|
if self.image:
|
||||||
|
self.image.putpixel((self.x - 1, self.y - 1), color)
|
||||||
|
|
||||||
|
def get_num_painted(self):
|
||||||
|
return sum(len(row.values()) for row in self.panel.values())
|
||||||
|
|
||||||
|
def save_image(self, path):
|
||||||
|
if self.image:
|
||||||
|
self.image.rotate(90).save(path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,4 +1,4 @@
|
||||||
""" Intcode interpreter. Day 9. """
|
""" Intcode interpreter. Day 11. """
|
||||||
|
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
import sys
|
import sys
|
||||||
|
@ -25,16 +25,14 @@ class PMode(IntEnum):
|
||||||
|
|
||||||
class Intcode(object):
|
class Intcode(object):
|
||||||
|
|
||||||
def __init__(self, program, print_output=False, debug=False):
|
def __init__(self, program, debug=False):
|
||||||
self._memory = program.copy()
|
self._memory = program.copy()
|
||||||
self.ip = 0
|
self.ip = 0
|
||||||
self.rel_base = 0
|
self.rel_base = 0
|
||||||
self.inputs = []
|
|
||||||
self.ctx_op = None
|
self.ctx_op = None
|
||||||
self.ctx_modes = None
|
self.ctx_modes = None
|
||||||
self.halt = False
|
self.halt = False
|
||||||
self.outputs = []
|
self.inputs = None
|
||||||
self.print_output = print_output
|
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -51,7 +49,6 @@ class Intcode(object):
|
||||||
while not self.halt:
|
while not self.halt:
|
||||||
self.read_code()
|
self.read_code()
|
||||||
handlers.get(self.ctx_op)()
|
handlers.get(self.ctx_op)()
|
||||||
return self.outputs[-1] if self.outputs else 0
|
|
||||||
|
|
||||||
def get_handlers(self):
|
def get_handlers(self):
|
||||||
return {
|
return {
|
||||||
|
@ -115,13 +112,11 @@ class Intcode(object):
|
||||||
self.ip += 4
|
self.ip += 4
|
||||||
|
|
||||||
def op_in(self):
|
def op_in(self):
|
||||||
self.mem_set(self.param(1, pointer=True), self.inputs.pop(0))
|
self.mem_set(self.param(1, pointer=True), self.input_data())
|
||||||
self.ip += 2
|
self.ip += 2
|
||||||
|
|
||||||
def op_out(self):
|
def op_out(self):
|
||||||
self.outputs.append(self.param(1))
|
self.output_data(self.param(1))
|
||||||
if self.print_output:
|
|
||||||
print(">", self.outputs[-1])
|
|
||||||
self.ip += 2
|
self.ip += 2
|
||||||
|
|
||||||
def op_jnz(self):
|
def op_jnz(self):
|
||||||
|
@ -150,3 +145,9 @@ class Intcode(object):
|
||||||
|
|
||||||
def op_halt(self):
|
def op_halt(self):
|
||||||
self.halt = True
|
self.halt = True
|
||||||
|
|
||||||
|
def input_data(self):
|
||||||
|
return self.inputs.pop(0)
|
||||||
|
|
||||||
|
def output_data(self, data):
|
||||||
|
print(">", data)
|
||||||
|
|
Loading…
Reference in a new issue