class Arcade: """ Executes the given intcode program, to play a game""" def __init__(self, intcode: List[int]): self.intcode = intcode self.current_position = (0, 0) self.screen = defaultdict(int) self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output) self.offset = 0 self.score = 0 def get_input(self): return 0 def generate_output(self, value: int): if self.offset == 0: self.x = value self.offset += 1 elif self.offset == 1: self.y = value self.offset += 1 elif self.offset == 2: if self.x == -1 and self.y == 0: logging.warning(f"Setting score to {value}") self.score = value else: logging.warning( f"Setting tile in {self.x},{self.y} with {value}") self.screen[(self.x, self.y)] = value self.offset = 0 def execute(self): self.intcode_computer.execute()
class PaintingRobot: """ Executes the given intcode program, painting tiles based on its output""" def __init__(self, intcode: List[int]): self.intcode = intcode self.current_position = (0, 0) self.orientation = (0, 1) self.painting_area = defaultdict(int) self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output) self.waiting_for_direction = False def get_input(self): logging.info( f"Reading tile {self.current_position} with color {self.painting_area[self.current_position]}" ) return self.painting_area[self.current_position] def generate_output(self, x: int): if self.waiting_for_direction: if x == 0: # Turn left 90 degrees if self.orientation == (0, 1): self.orientation = (-1, 0) elif self.orientation == (-1, 0): self.orientation = (0, -1) elif self.orientation == (0, -1): self.orientation = (1, 0) elif self.orientation == (1, 0): self.orientation = (0, 1) else: if self.orientation == (0, 1): self.orientation = (1, 0) elif self.orientation == (-1, 0): self.orientation = (0, 1) elif self.orientation == (0, -1): self.orientation = (-1, 0) elif self.orientation == (1, 0): self.orientation = (0, -1) self.current_position = (self.current_position[0] + self.orientation[0], self.current_position[1] + self.orientation[1]) self.waiting_for_direction = False logging.info( f"Updated orientation to {self.orientation} and position to {self.current_position}" ) else: logging.info(f"Painting {self.current_position} with {x}") self.painting_area[self.current_position] = x self.waiting_for_direction = True def execute(self): self.intcode_computer.execute()
class Robot(): move = { direction.UP : lambda c : (c[0],c[1]+1), direction.DOWN : lambda c : (c[0],c[1]-1), direction.LEFT : lambda c : (c[0]-1,c[1]), direction.RIGHT : lambda c : (c[0]+1,c[1]), } def __init__(self, prog): self.p = direction.UP # pointing self.loc = (0,0) self.grid = {} self.grid[self.loc] = 1 self.brain = IntcodeComputer([], prog) self.painted = [] self.paint() def rotate(self, by): if self.p == direction.UP: self.p = direction.LEFT if by == 0 else direction.RIGHT elif self.p == direction.DOWN: self.p = direction.RIGHT if by == 0 else direction.LEFT elif self.p == direction.RIGHT: self.p = direction.UP if by == 0 else direction.DOWN elif self.p == direction.LEFT: self.p = direction.DOWN if by == 0 else direction.UP def paint(self): while(True): try: col = self.grid[self.loc] except: col = 0 self.grid[self.loc] = col self.brain.outputs = [] self.brain.input = [col]*100000 self.brain.execute() if len(self.brain.outputs) > 0: paint, turn = self.brain.outputs[0], self.brain.outputs[1] #print(paint, turn) self.grid[self.loc] = paint self.painted.append(self.loc) self.rotate(turn) self.loc = self.move[self.p](self.loc) else: break
class PaintingRobot: """ Executes the given intcode program, painting tiles based on its output""" def __init__(self, intcode: List[int]): self.intcode = intcode self.current_position = (0, 0) self.orientation = (0, 1) self.painting_area = defaultdict(int) self.painting_area[self.current_position] = 1 self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output) self.waiting_for_direction = False def get_input(self): logging.info( f"Reading tile {self.current_position} with color {self.painting_area[self.current_position]}" ) return self.painting_area[self.current_position] def update_orientation(self, turn_to: int): x, y = self.orientation # Change sign if x=0 and have to turn left, or if x=1 and have to turn right sign = -1 if abs(x) == turn_to else 1 self.orientation = (sign * y, sign * x) def generate_output(self, value: int): if self.waiting_for_direction: self.update_orientation(value) ox, oy, x, y = (*self.orientation, *self.current_position) self.current_position = (x + ox, y + oy) self.waiting_for_direction = False logging.info( f"Updated orientation to {self.orientation} and position to {self.current_position}" ) else: logging.info(f"Painting {self.current_position} with {value}") self.painting_area[self.current_position] = value self.waiting_for_direction = True def execute(self): self.intcode_computer.execute()
async def part2(): input = asyncio.Queue() output = asyncio.Queue() computer = IntcodeComputer('day17.txt', input, output) computer._state._memory[0] = 2 tasks = [ asyncio.create_task(inout_handler(input, output)), asyncio.create_task(computer.execute()) ] await asyncio.gather(*tasks) print('Part 2 complete')
class Amplifier: """ Executes the given intcode program, adjusted by the phase and initial signal value provided It will read further required inputs from input_signal, and output any generated signal to output_signal """ def __init__(self, id: int, intcode: List[int], phase: int, initial_signal_value: int = None, input_queue=None, output_queue=None): self.intcode = intcode self.id = id self.phase = phase self.input_queue = input_queue self.input_queue.put(phase) if initial_signal_value != None: self.input_queue.put(initial_signal_value) self.output_queue = output_queue self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output) def get_input(self): value = self.input_queue.get() logging.info(f"Got {value} value from queue in amplifier {self.id}") return value def generate_output(self, x: int): self.last_value = x self.output_queue.put(x) def execute(self): logging.info(f"Starting amplifier with phase {self.phase}") self.intcode_computer.execute()
# Part 1 computer.run(program_code, inputs) outputs = computer.outputs tiles = process_outputs(outputs) num_blocks = sum([1 for x in tiles if x[2] == 2]) print('Num blocks:', num_blocks) assert num_blocks == 344 # Part 2 program_code[0] = 2 computer.initialize(program_code, inputs) score = 0 while True: computer.reset_outputs() done = computer.execute() outputs = computer.outputs if not render: print('outputs', outputs) tiles = process_outputs(outputs) for x, y, id in tiles: if x == -1 and y == 0: score = id if score > 0: num_blocks -= 1 if not render: print('Display score:', score, '- Remaining blocks:', num_blocks) if id == 3: x_paddle = x
class NetworkComputer: """ Executes the given intcode program, to act as a Network computer""" def __init__(self, _id: int, intcode: List[int], queues: List[queue.Queue], nat_queue: queue.Queue): self.intcode = intcode self.id = _id self.network_address = -1 self.queue_list = queues self.nat_queue = nat_queue self.intcode_computer = IntcodeComputer(intcode, self.get_input, self.generate_output) self.next_output = 0 self.current_incoming_packet = None self.current_outgoing_packet = None self.send_to_address = None self.waiting_input = False def get_input(self): if self.network_address < 0: self.network_address = self.id print( f"Computer {self.id} got network adress {self.network_address}" ) return self.network_address if self.current_incoming_packet: value = self.current_incoming_packet.pop() print(f"Computer {self.id} getting {value} from existing packet") return value else: try: self.current_incoming_packet = self.queue_list[ self.id].get_nowait() print( f"Computer {self.id} receiving {self.current_incoming_packet}" ) self.waiting_input = False return self.current_incoming_packet.pop() except: self.waiting_input = True return -1 def generate_output(self, value: int): self.waiting_input = False if self.next_output == 0: self.send_to_address = value self.next_output += 1 elif self.next_output == 1: self.current_outgoing_packet = [value] self.next_output += 1 elif self.next_output == 2: self.current_outgoing_packet.append(value) to_send = list(reversed(self.current_outgoing_packet)) if self.send_to_address == 255: print(f"**** Sending {to_send} to NAT ****") self.nat_queue.put_nowait(to_send) else: print( f"Computer {self.id} sending {to_send} to address {self.send_to_address}" ) self.queue_list[self.send_to_address].put_nowait(to_send) self.next_output = 0 def execute(self): print(f"Computer {self.id} starting...") self.intcode_computer = IntcodeComputer(self.intcode, self.get_input, self.generate_output) self.intcode_computer.execute()
items = [ 'boulder', 'shell', 'mug', 'hypercube', 'space law space brochure', 'festive hat', 'astronaut ice cream', 'whirled peas' ] for i in reversed(range(1, 8)): print('\nTesting 8 choose', i, '\n') combos = combinations(items, i) for combo in list(combos): print('Combo:', combo) cmds = get_item_cmds(items, combo) inputs.clear() inputs.extend(get_inputs(cmds)) computer.reset_outputs() computer.execute() status_map = process_outputs(computer.outputs) text = render(status_map, False) if 'lighter' in text: print(' lighter') if 'heavier' in text: print(' heavier') if 'ejected back to the checkpoint' not in text: print(text) exit(0) # Items in your inventory: # - hypercube # - festive hat # - shell # - astronaut ice cream
def main(intcode: List[int] = None): if not intcode: intcode = read_input(input_file=_INPUT_FILE) intcode_computer = IntcodeComputer(intcode, lambda: 2, lambda x: print(f"BOOST keycode: {x}")) intcode_computer.execute()
linestr = ' ' i = 0 for x in range(min_x, max_x): if i % 5 == 0: linestr = linestr + str(i) else: linestr = linestr + ' ' i += 1 gridstr = gridstr + (linestr + '\n') print(gridstr) brain = IntcodeComputer([], prog) brain.execute() j = 0 # ind = 114 inp_seq = [1] + ([0]*45) + [-1,-1] + ([0]*12) + [-1,-1] + ([0]*44) + [-1,-1,-1,-1] \ + ([0]*25) + [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] + ([0]*33) + [1,1,1,1,1,1,1,1,1,-1,-1,-1] \ + ([0]*30) + ([1]*15) + [-1,-1] + ([0]*30) + ([1]*6) + ([-1]*6) + ([-1]*15) + ([0]*5) + ([1]*3) \ + ([0]*140) + ([1]*8) + ([0]*50) + ([1]*2) + ([0]*10) + ([-1]*10) + ([0]*40) + ([1]*9) +([0]*37) \ + ([1]*7) + ([-1]*2) + ([0]*20) + ([1]*10) + ([0]*100) + ([-1]*15) + ([0]*30) + ([-1]*6) + ([0]*3) + ([1]*3) \ + ([0]*425) + ([1]*12) + ([0]*120) + ([1]*14) + ([0]*65) + ([-1]*8) + ([0]*240) + ([-1]*27) + ([0]*27) + ([1]*35) \ + [-1] + ([0]*5) + ([-1]*33) + ([0]*23) + [1] + ([0]*26) + ([1]*33) + [0] + [-1] + ([0]*3) + ([-1]*32) + [0] \ + [-1] + ([0]*250) + ([1]*22) + ([0]*8) + ([-1]*22) + ([0]*10) + ([1]*22) + ([0]*5) + ([-1]*22) + ([0]*8) \ + ([1]*21) + ([0]*50) + ([-1]*9) + ([0]*70) + ([1]*12) + ([0]*25) + ([-1]*12) + ([0]*3) + ([1]*12) \ + ([0]*35) + ([-1]*12) + ([0]*10) + ([1]*12) + ([0]*15) + ([-1]*12) + ([0]*20) + ([1]*12) \ + ([0]*30) + ([-1]*11) + ([0]*33) + ([1]*13) + ([0]*54) + ([-1]*31) + ([1]*30) + ([0]*10) \