class SpringDroidProgrammer: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day21input.txt')) self.ic.start() def read_prompt(self): rtn = '' ch = self.ic.read_output() while ch != 10: rtn += chr(ch) ch = self.ic.read_output() return rtn def write_command(self, command): for ch in command: self.ic.write_input(ord(ch)) self.ic.write_input(10) def read_output(self): while not self.ic.finished: ch = self.ic.read_output() if ch < 256: pass else: return ch def program(self, source): self.read_prompt() for line in source.splitlines(): if sline := line.strip(): self.write_command(' '.join(sline.split()))
class NetworkInterfaceController: def __init__(self, address): self.address = address self.input_q = deque() self._idle_counter = 0 self.ic = Intcode(read_comma_separated_integers('day23input.txt')) self.ic.start() self.ic.write_input(address) def __repr__(self): return f'<NIC {self.address!r}>' def communicate(self, network): if self.ic.requires_input: if self.input_q: self.ic.write_input(self.input_q.popleft()) self._idle_counter = 0 else: self.ic.write_input(-1) self._idle_counter += 1 else: # if it is not taking an input, assume it has 3 outputs addr = self.ic.read_output() x = self.ic.read_output() y = self.ic.read_output() network.transmit(self.address, addr, x, y) self._idle_counter = 0 def receive(self, x, y): self.input_q.append(x) self.input_q.append(y) def is_idle(self): return self._idle_counter > 50
class ArcadeCabinet: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day13input.txt')) self.screen = {} self.score = 0 def set_number_of_quarters(self, value): self.ic.memory[0] = value def read_tile_from_ic(self): data = [] while len(data) < 3 and not self.ic.finished: if self.ic.requires_input: self.ic.write_input(self.joystick_value) else: data.append(self.ic.read_output()) if len(data) == 3: return tuple(data) def run(self): self.ic.start() while None is not (tile := self.read_tile_from_ic()): x, y, tile_id = tile if (x, y) == (-1, 0): self.score = tile_id continue self.screen[(x, y)] = TileId(tile_id)
class EmergencyHulPaintingProgram: DIRECTIONS = (0, 1), (1, 0), (0, -1), (-1, 0) # up, right, down, left def __init__(self, hul: dict): self.ic = Intcode(read_comma_separated_integers('day11input.txt')) self.ic.start() self.hul = hul self.position = 0, 0 self.direction_index = 0 def _read_value(self): while True: if self.ic.requires_input: self.ic.write_input(self.hul.get(self.position, 0)) else: return self.ic.read_output() def _rotate(self, value): rotation = 1 if value else -1 self.direction_index = (self.direction_index + rotation) % 4 x, y = self.position dx, dy = self.DIRECTIONS[self.direction_index] self.position = x + dx, y + dy def paint(self): while not self.ic.finished: color = self._read_value() self.hul[self.position] = color rotation = self._read_value() self._rotate(rotation)
def _test_coordinates(self, x, y): assert 0 <= x <= self.max_coord assert 0 <= y <= self.max_coord ic = Intcode(self.opcodes) ic.start() ic.write_input(x) ic.write_input(y) return {1: True, 0: False}[ic.read_output()]
def part1(data): cpu = Intcode() cpu.set_ascii_mode(True) cpu.load_program(data) while True: try: cpu.run() except KeyboardInterrupt: pass print(''.join([chr(c) for c in cpu.read_output()]))
class DiagnosticProgram: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day5input.txt')) def run(self, system_id): self.ic.start() self.ic.write_input(system_id) while not self.ic.finished: yield self.ic.read_output()
class BoostProgram: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day9input.txt')) def _read_all(self): while not self.ic.finished: yield self.ic.read_output() def run(self, input_value): self.ic.start() self.ic.write_input(input_value) return list(self._read_all())
class AftScaffoldingControlAndInformationInterface: def __init__(self, wake_vacuum_robot_up=False): opcodes = read_comma_separated_integers('day17input.txt') if wake_vacuum_robot_up: assert opcodes[0] == 1 opcodes[0] = 2 self.ic = Intcode(opcodes) self.ic.start() def scan_cameras(self): line = [] while True: while (ch := self.ic.read_output()) != 10: if ch is None: break line.append(chr(ch)) if line: yield ''.join(line) line = [] else: return
class Amplifier: def __init__(self, phase_setting): self.ic = Intcode(read_comma_separated_integers('day7input.txt')) self.ic.start() self.ic.write_input(phase_setting) def run(self, input_value): self.ic.write_input(input_value) return self.ic.read_output() @property def finished(self): return self.ic.finished
class DroidRemote: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day15input.txt')) self.ic.start() def move(self, direction): command = { Direction.NORTH: 1, Direction.SOUTH: 2, Direction.WEST: 3, Direction.EAST: 4 }[direction] self.ic.write_input(command) return Status(self.ic.read_output())
def part1(data): cpu = Intcode() cpu.load_program(data) cpu.run() scaf = ''.join([chr(c) for c in cpu.read_output()]).strip().split('\n') scafpts = [(x, y) for y, line in enumerate(scaf) for x, c in enumerate(line) if c == '#'] isect = [] for pt in scafpts: ptx, pty = pt if all([(x, y) in scafpts for x, y in ((ptx + 1, pty), (ptx - 1, pty), (ptx, pty - 1), (ptx, pty + 1))]): isect.append((ptx, pty)) return sum((x * y for x, y in isect))
def part1(data): prog = '\n'.join(( 'NOT C J', 'AND D J', 'NOT A T', 'OR T J', 'WALK\n', )) cpu = Intcode() cpu.load_program(data) cpu.set_ascii_mode(True) cpu.feed_inputs(*prog) cpu.run() out = cpu.read_output() try: print(''.join([chr(c) for c in out])) except ValueError: return (out[-1])
def part2(data): prog = '\n'.join(( 'NOT I J', 'AND H J', 'NOT F T', 'AND G T', 'OR T J', 'AND D J', 'AND H J', 'NOT A T', 'OR T J', 'NOT C T', 'AND D T', 'OR T J', # 'NOT C T', # 'AND D T', # 'OR T J', 'RUN\n', )) prog = '\n'.join(('NOT A T', 'OR T J', 'AND G T', 'AND D T', 'AND H T', 'OR T J', 'NOT C T', 'AND D T', 'OR T J', 'RUN\n')) prog = '\n'.join(('NOT A J', 'OR E T', 'OR C T', 'NOT T T', 'AND D T', 'OR T J', 'OR B T', 'OR E T', 'NOT T T', 'OR T J', 'NOT I T', 'AND D T', 'OR T J', 'RUN\n')) cpu = Intcode() cpu.load_program(data) cpu.set_ascii_mode(True) cpu.feed_inputs(*prog) cpu.run() out = cpu.read_output() try: print(''.join([chr(c) for c in out])) except ValueError: return (out[-1]) test_springscript(prog)
def part2(data): cpu = Intcode(wfi_mode=True) cpu.set_ascii_mode(True) cpu.load_program(data) cpu.ram[0] = 2 cpu.run() cpu.feed_inputs( * 'A,B,A,B,C,C,B,A,C,A\nL,10,R,8,R,6,R,10\nL,12,R,8,L,12\nL,10,R,8,R,8\nn\n' ) cpu.run() #cam = ''.join([chr(x) if chr(x).isprintable() or x == 10 and x < 0x110000 else str(x) for x in cpu.read_output() ]).strip().split('\n') cam = cpu.read_output() print(cam) ''' from PIL import Image img = Image.new('RGB', (len(cam[0]), len(cam)), 'black') pix = img.load() for y, line in enumerate(cam): print(line) for x, char in enumerate(line): if char == '#': pix[x,y] = (0, 255, 128) img.save('day17.bmp') ''' # L10 R8 R6 R10 L12 R8 L12 L10 R8 R6 R10 L12 R8 L12 L10 R8 R8 L10 R8 R8 L12 R8 L12 L10 R8 R6 R10 L10 R8 R8 L10 R8 R6 R10 # L10 R8 R6 R10 = A # L12 R8 L12 = B # L10 R8 R8 = C # A B A B C C B A C A print(cpu.outputs)
class Robot: def __init__(self): self.ic = Intcode(read_comma_separated_integers('day25input.txt')) self.ic.start() def run_manually(self): print(self._read_output(), end='') while self.ic.requires_input: txt = input() self.write_input(f'{txt}\n') print(self._read_output(), end='') def go(self, direction) -> Room: self.write_input(f'{direction}\n') return self.read_room_info() def take(self, item): self.write_input(f'take {item}\n') output = self.parse_output() assert output['lines'] == [f'You take the {item}.'] def drop(self, item): self.write_input(f'drop {item}\n') output = self.parse_output() assert output['lines'] == [f'You drop the {item}.'] def inv(self): self.write_input(f'inv\n') output = self.parse_output() if output['lines'] == ["You aren't carrying any items."]: return [] else: return output['Items in your inventory:'] def write_input(self, s): for ch in s: self.ic.write_input(ord(ch)) def _read_output(self): rtn = [] while self.ic.has_output: rtn.append(chr(self.ic.read_output())) return ''.join(rtn) def parse_output(self): rtn = {'lines': []} list_name = None end = False for line in self._read_output().splitlines(): assert not end if line.endswith(':'): assert not list_name list_name = line rtn[list_name] = [] elif not line: list_name = None elif list_name: assert line.startswith('- ') rtn[list_name].append(line[2:]) elif line == 'Command?': end = True else: rtn['lines'].append(line) return rtn def read_room_info(self) -> Room: output = self.parse_output() lines = output['lines'] assert lines[0].startswith('== ') and lines[0].endswith(' ==') room_name = lines[0][3:-3] doors = output.get('Doors here lead:', []) items = output.get('Items here:', []) TOO_LIGHT = 'A loud, robotic voice says '\ '"Alert! Droids on this ship are heavier than the detected value!"'\ ' and you are ejected back to the checkpoint.' TOO_HEAVY = 'A loud, robotic voice says '\ '"Alert! Droids on this ship are lighter than the detected value!"'\ ' and you are ejected back to the checkpoint.' if TOO_LIGHT in lines: raise SecurityCheckpointFailed(False) if TOO_HEAVY in lines: raise SecurityCheckpointFailed(True) for line in lines: if m := re.search( r'You should be able to get in by typing (\d+) on the keypad', line): raise PasswordFound(m.group(1)) return Room(room_name=room_name, doors=doors, items=items)