def run_row(prog, row, xs, xe): print("run_row()", row, xs, xe) context = { "output": [0 for x in range(xs, xe + 1)], "curr_pos": [xs, row], "input_axis": 0, } def handle_input(): axis = context["input_axis"] res = context["curr_pos"][axis] #print("Axis {}: {}".format(axis, res)) context["input_axis"] = (context["input_axis"] + 1) % 2 return res def handle_output(x): coord = context["curr_pos"] context["output"][coord[0] - xs] = x context["curr_pos"][0] += 1 while context["curr_pos"][0] < xe: vm_prog = intcode.load_program(prog.copy()) intcode.run_until_halt(vm_prog, handle_input, handle_output) if 1 in context["output"]: first_one = xs + context["output"].index(1) last_one = xs + len( context["output"]) - context["output"][::-1].index(1) else: first_one = 0 last_one = 0 return (context["output"], first_one, last_one)
def run_row(row): global GRID, PROG context = { "curr_pos": [0, row], "input_axis": 0, } def handle_input(): axis = context["input_axis"] res = context["curr_pos"][axis] context["input_axis"] = (context["input_axis"] + 1) % 2 return res def handle_output(x): coord = context["curr_pos"] GRID[(coord[1] * 50) + coord[0]] = x context["curr_pos"][0] += 1 if context["curr_pos"][0] >= 50: context["curr_pos"][1] += 1 context["curr_pos"][0] = 0 while context["curr_pos"][1] == row: vm_prog = intcode.load_program(PROG) intcode.run_until_halt(vm_prog, handle_input, handle_output)
def run_program_step1(prog): context = { "grid": [[0 for x in range(50)] for y in range(50)], "curr_pos": [0, 0], "input_axis": 0, } def handle_input(): axis = context["input_axis"] res = context["curr_pos"][axis] #time.sleep(0.1) #print("Axis {}: {}".format(axis, res)) context["input_axis"] = (context["input_axis"] + 1) % 2 return res def handle_output(x): coord = context["curr_pos"] context["grid"][coord[1]][coord[0]] = x context["curr_pos"][0] += 1 if context["curr_pos"][0] >= 50: context["curr_pos"][1] += 1 context["curr_pos"][0] = 0 while context["curr_pos"][1] < 50: vm_prog = intcode.load_program(prog.copy()) intcode.run_until_halt(vm_prog, handle_input, handle_output) return context
def test_large_ints(): # Should output a 16-digit number prog = [1102, 34915192, 34915192, 7, 4, 7, 99, 0] output = [] res = run_until_halt(load_program(prog), output_cb=lambda x: output.append(x)) assert len(output) == 1 and len(str(output[0])) == 16 # Should output the number in the middle prog = [104, 1125899906842624, 99] output = [] res = run_until_halt(load_program(prog), output_cb=lambda x: output.append(x)) assert len(output) == 1 and output[0] == 1125899906842624
def run_program(prog, start_panel_colour): context = { "cells": defaultdict(lambda: 0), "curr_pos": [0, 0], "direction": 0, "output_mode": 0, } context["cells"][(0, 0)] = start_panel_colour def handle_input(): # Robot's camera: return the value of the current cell return context["cells"][tuple(context["curr_pos"])] def handle_output(x): if context["output_mode"] == 0: # Paint the current cell context["cells"][tuple(context["curr_pos"])] = x # Change output_mode ready for next direction change context["output_mode"] = 1 else: # Rotate 90° left (0) or 90° right (1) if x == 0: context["direction"] = (context["direction"] - 1) % 4 elif x == 1: context["direction"] = (context["direction"] + 1) % 4 # Move forward 1 cell based on new direction if context["direction"] == 0: # UP context["curr_pos"][1] -= 1 elif context["direction"] == 1: # RIGHT context["curr_pos"][0] += 1 elif context["direction"] == 2: # DOWN context["curr_pos"][1] += 1 elif context["direction"] == 3: # LEFT context["curr_pos"][0] -= 1 # Reset output_mode ready for next paint context["output_mode"] = 0 # Run the painting robot's program until it halts, handling input and # output using the above functions intcode.run_until_halt(prog, handle_input, handle_output) return context
def run_program_step2(prog, view_feed, seq): # TODO: parse movement sequence and find longest repeating patterns for function definitions # TODO: convert 3 longest repeated sequences to function definitions and update main_routine to be a list of function calls print("TODO: compress sequence: {}".format(seq)) main_routine = "A,A,B,C,B,C,B,C,B,A" functions = [ "R,10,L,12,R,6", "R,6,R,10,R,12,R,6", "R,10,L,12,L,12", ] context = { "output": "", "input_idx": 0, } # Concatenate the main_routine, functions and live feed answer to a # single string of characters to sent as input to the robot command_str = main_routine + "\n" + "\n".join(functions) + "\n" + ( "y" if view_feed else "n") + "\n" def handle_input(): res = 0 if context["input_idx"] < len(command_str): res = ord(command_str[context["input_idx"]]) context["input_idx"] += 1 return res def handle_output(x): if view_feed: if x == 10: context["output"] += "\n" print(context["output"]) else: context["output"] += chr(x) else: context["output"] = x # Wake up robot prog[0] = 2 prog = intcode.load_program(prog) intcode.run_until_halt(prog, handle_input, handle_output) return context
def run_program_step1(prog): context = { "output": "", } def handle_input(): return 0 def handle_output(x): if x == 10: context["output"] += "\n" else: context["output"] += chr(x) prog = intcode.load_program(prog) intcode.run_until_halt(prog, handle_input, handle_output) return context
def test_quine(): prog = [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ] output = [] res = run_until_halt(load_program(prog), output_cb=lambda x: output.append(x)) assert output == prog
def main(): progs = [ [1, 0, 0, 0, 99], [2, 3, 0, 3, 99], [2, 4, 4, 5, 99, 0], [1, 1, 1, 4, 99, 5, 6, 0, 99], [1, 1, 1, 4, 99, 5, 6, 0, 99], [1002, 4, 3, 4, 33], # LESS THAN and EQUALS tests [3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8], [3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8], [3, 3, 1108, -1, 8, 3, 4, 3, 99], [3, 3, 1107, -1, 8, 3, 4, 3, 99], # JUMP tests [3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9], [3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1], [ 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99 ], # Quine [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ] ] for prog in progs: run_and_disassemble(prog) with open("../09/input.txt", "rt") as f: prog = [int(x) for x in f.read().strip().split(",") if len(x) > 0] print("Disassembling BOOST (test mode)...") prog_c = intcode.load_program(prog) for ctx in intcode.run_single_steps(prog_c, input_cb=lambda: 1): print(intcode.disassemble(ctx, prog_c)) print("") print("Running BOOST (full)...") intcode.run_until_halt(intcode.load_program(prog), input_cb=lambda: 2) print("DONE")
def test_complex(): prog = load_program([ 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4, 20, 1105, 1, 46, 98, 99 ]) for test in [(7, 999), (8, 1000), (9, 1001)]: output = [] res = run_until_halt(prog.copy(), lambda: test[0], lambda x: output.append(x)) assert output[0] == test[1]
def test_simple(): programs = [ ([1, 0, 0, 0, 99], [2, 0, 0, 0, 99]), ([2, 3, 0, 3, 99], [2, 3, 0, 6, 99]), ([2, 4, 4, 5, 99, 0], [2, 4, 4, 5, 99, 9801]), ([1, 1, 1, 4, 99, 5, 6, 0, 99], [30, 1, 1, 4, 2, 5, 6, 0, 99]), ([1, 1, 1, 4, 99, 5, 6, 0, 99], [30, 1, 1, 4, 2, 5, 6, 0, 99]), ([1002, 4, 3, 4, 33], [1002, 4, 3, 4, 99]), ] for prog in programs: res = run_until_halt(load_program(prog[0]), lambda: 0, lambda x: 0) assert list(res.values()) == prog[1]
def test_less_than_equals(): programs = [ ([3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8], [(8, 1), (7, 0), (9, 0)]), ([3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8], [(8, 0), (7, 1), (9, 0)]), ([3, 3, 1108, -1, 8, 3, 4, 3, 99], [(8, 1), (7, 0), (9, 0)]), ([3, 3, 1107, -1, 8, 3, 4, 3, 99], [(8, 0), (7, 1), (9, 0)]), ] for prog in programs: for test in prog[1]: output = [] res = run_until_halt(load_program(prog[0]), lambda: test[0], lambda x: output.append(x)) assert output[0] == test[1]
def test_jumps(): programs = [ ([3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9], [(-1, 1), (0, 0), (1, 1)]), ([3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1], [(-1, 1), (0, 0), (1, 1)]), ] for prog in programs: for test in prog[1]: output = [] res = run_until_halt(load_program(prog[0]), lambda: test[0], lambda x: output.append(x)) assert output[0] == test[1]
def test_examples(): # Quine (should output a copy of itself) prog = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99] output = [] intcode.run_until_halt(prog.copy(), lambda: 0, lambda x: output.append(x)) assert output == prog # Should output a 16-digit number prog = [1102,34915192,34915192,7,4,7,99,0] output = [] intcode.run_until_halt(prog, lambda: 0, lambda x: output.append(x)) assert len(output) == 1 and len(str(output[0])) == 16 # Should output the second large value prog = [104,1125899906842624,99] output = [] intcode.run_until_halt(prog, lambda: 0, lambda x: output.append(x)) assert len(output) == 1 and output[0] == prog[1]
def run_BOOST(mode): program = get_input() output = [] intcode.run_until_halt(program.copy(), lambda: mode, lambda x: output.append(x)) return output
def run_program(prog, quarters): context = { "cells": defaultdict(lambda: " "), "draw_pos": [0, 0], "output_mode": 0, "score": 0, } # "Insert" quarters if necessary if quarters is not None: prog[0] = quarters def handle_input(): # Obtain position of the ball ("O") and bat ("=") and return # the appropriate joystick input (left: -1, right: 1, centered: # 0) to try to keep the bat below the ball ball_pos = get_element_pos(context["cells"], "O") bat_pos = get_element_pos(context["cells"], "=") if ball_pos is None or bat_pos is None: return 0 if ball_pos[0] < bat_pos[0]: return -1 elif ball_pos[0] > bat_pos[0]: return 1 else: return 0 def handle_output(x): # Set X coordinate if context["output_mode"] == 0: context["draw_pos"][0] = x context["output_mode"] += 1 # Set Y coordinate elif context["output_mode"] == 1: context["draw_pos"][1] = x context["output_mode"] += 1 # Set tile ID elif context["output_mode"] == 2: pos = tuple(context["draw_pos"]) if pos == (-1, 0): context["score"] = x else: context["tile_id"] = x # Update grid if x == 1: ch = "#" elif x == 2: ch = "x" elif x == 3: ch = "=" elif x == 4: ch = "O" else: ch = " " context["cells"][pos] = ch # Reset output_mode back to 0 (set X) context["output_mode"] = 0 # Run the game until it halts intcode.run_until_halt(prog, handle_input, handle_output) return context