def check_phase_settings_loop(program, phase_settings): amplifiers = [] for i in range(5): cpu = intcode.CPU(memory=program.copy(), input=[phase_settings[i]]) amplifiers.append(cpu) last_output = 0 amplifier_idx = 0 while True: cpu = amplifiers[amplifier_idx] # print(f"amplifier {amplifier_idx} last_interrupt {cpu.last_interrupt}") if cpu.last_interrupt == intcode.Interrupt.HALT: # print(f"amplifier {amplifier_idx} stopped") if amplifier_idx == 4: break else: amplifier_idx += 1 continue # print(f"amplifier {amplifier_idx} add_input {last_output}") cpu.add_input(last_output) cpu.execute_until_interrupt() last_output = cpu.last_output() if amplifier_idx == 4: amplifier_idx = 0 else: amplifier_idx += 1 return last_output
def runNATnetwork(ins): global inputQueues nics = [intcode.CPU(ins, inGen(x), outGen(x)) for x in range(50)] previousY = [math.inf] while not all([nic.finished() for nic in nics]): for n in nics: n.run(1) # Check the NAT status - remember only last packet if len(inputQueues[255]) > 1: inputQueues[255] = [inputQueues[255][-1]] # Check network status if all([len(inputQueues[x]) == 0 for x in range(50)] + [len(inputQueues[255]) > 0]): # It's idle! Send to 0, but check for the double send previousY.append(inputQueues[255][0][1]) if previousY[0] == previousY[1]: raise Exception("Part 2: Sent Y", previousY[0], "back to back from NAT") else: previousY.pop(0) inputQueues[0].append(inputQueues[255].pop())
def paint(hull, ins): pos = complex(0,0) mov = complex(0,1) painted = set() def outputer(): mode = 0 TURN = [1j, -1j] def o(x): # I don't love having to use nonlocal, but... nonlocal mode nonlocal pos nonlocal mov if mode == 0: hull[pos] = x painted.add(pos) else: mov *= TURN[x] pos += mov mode = (mode+1)%2 return o def input(): while True: yield hull[pos] cpu = intcode.CPU(ins,input, outputer()) while not cpu.finished(): cpu.run() return painted
def test_case3(): prog = [104, 1125899906842624, 99] cpu = intcode.CPU(code=prog) # print("") # cpu.debug = True cpu.execute() # print("case3 output:", cpu.output) assert [1125899906842624] == cpu.output
def check_phase_settings(program, phase_settings): last_output = 0 for i in range(5): cpu = intcode.CPU(memory=program.copy(), input=[phase_settings[i], last_output]) cpu.execute() last_output = cpu.last_output() return last_output
def runNetwork(ins): global inputQueues nics = [intcode.CPU(ins, inGen(x), outGen(x)) for x in range(50)] while not all([nic.finished() for nic in nics]): for n in nics: n.run(1) if len(inputQueues[255]) != 0: raise Exception("Part 1: ", inputQueues[255][0][1])
def test_case1(): prog = [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ] cpu = intcode.CPU(code=prog) # print() # cpu.debug = True cpu.execute() assert cpu.output == prog
def spring(ins, command): def outputter(x): if x <= 127: if chr(x) in PRINTABLE: print(chr(x), end='') else: raise Exception("Unexpected chr") else: print("End of path:", x) cpu = intcode.CPU(ins, command, outputter) cpu.run()
def test_case2(): prog = [ 1102, 34915192, 34915192, 7, # write 1219070632396864 to [7] (last elem) 4, 7, # re 99, 0 ] cpu = intcode.CPU(code=prog) # print("") # cpu.debug = True cpu.execute() assert 16 == len(str(cpu.last_output()))
def runAdventure(ins): def outputter(x): if x < 128: print(chr(x), end='') else: raise Exception("NotASCII") def inputter(): commands = [ "east", "east", "take fuel cell", "west", "take jam", "south", "take shell", "north", "west", "south", "west", "take easter egg", "north", "east", "take space heater", "west", "south", "west", "west", "take monolith", "south", "west", "north", "take coin", "south", "east", "north", "west", "take mug", "north", "drop jam", "drop easter egg", "drop monolith", "drop mug", "north" ] for c in commands: for l in c: yield (ord(l)) yield (10) # We are now at checkpoint - code below exhausts the options, but I've added the requirements to the list above # before commiting #items = ["fuel cell", "jam", "shell", "easter egg", "space heater", "monolith", "coin", "mug"] #for numitems in range(8,0,-1): # for testcomb in itertools.combinations(items,numitems): # for item in items: # for l in "drop " + item: # yield(ord(l)) # yield(10) # for item in testcomb: # for l in "take " + item: # yield(ord(l)) # yield(10) # for l in "north": # yield(ord(l)) # yield(10) # #while True: # buffer = input("*INPUT*: ") # for c in buffer: # yield ord(c) # yield(10) adv = intcode.CPU(ins, inputter, outputter) adv.run()
def part2(ins): screen = collections.defaultdict(lambda: EMPTY, {}) score = 0 def outputter(): buf = [] def o(x): nonlocal buf nonlocal screen nonlocal score buf.append(x) if len(buf) == 3: pos = complex(buf[0], -buf[1]) if pos == complex(-1, 0): score = buf[2] else: screen[pos] = buf[2] buf = [] return o def input(): nonlocal screen nonlocal score while True: printscreen(screen, score) paddlex = [x for x in screen.keys() if screen[x] == PADDLE][0] ballx = [x for x in screen.keys() if screen[x] == BALL][0] if ballx.real < paddlex.real: yield -1 elif ballx.real > paddlex.real: yield 1 else: yield 0 ins[0] = 2 # Set free play cpu = intcode.CPU(ins, input, outputter()) while not cpu.finished(): cpu.run() return score
def part1(ins): screen = {} def outputter(): buf = [] def o(x): nonlocal buf nonlocal screen buf.append(x) if len(buf) == 3: pos = complex(buf[0], -buf[1]) screen[pos] = buf[2] buf = [] return o cpu = intcode.CPU(ins, None, outputter()) cpu.run() blocks = sum([1 for x in screen.values() if x == BLOCK]) return blocks
def findOxygen(ins): # Try building a graph of our progress G = networkx.Graph() G.add_node(0+0j) # Position pos = 0+0j options = {0+0j: [1,2,3,4]} path = [] reverse = False # Moving around is hard! def inputter(): nonlocal pos nonlocal reverse nonlocal path lastpos = pos while True: # We find ourselves at pos, with some options in options. Pick the next and # execute it if there are any. If no options remain, choose the direction to # send us back one if len(options[pos]) == 0: reverse = True yield pathrev[path[-1]] # This will throw when we've exhausted everything else: go = options[pos].pop(-1) path.append(go) yield go def outputter(response): nonlocal pos nonlocal reverse global oxygen if response == 0: # Hit a wall. Remove from path, don't update position path.pop(-1) else: if not reverse: # Found a spot we could move into. Could be a place we've encountered # before if there are loops newpos = pos + steps[path[-1]] # Add a link in the graph G.add_edge(pos, newpos) # Update pos pos = newpos if pos not in options: options[pos] = [x for x in range(1,5) if x != pathrev[path[-1]]] # Remeber if this is oxygen if response == 2: oxygen = pos else: # Unwind newpos = pos + steps[pathrev[path[-1]]] pos = newpos reverse = False path.pop(-1) cpu = intcode.CPU(ins, inputter, outputter) try: cpu.run() except Exception as e: pass return G
# # print(f"==SET INPUT: {color}") # cpu.set_input([color]) # continue # except intcode.HaltInt: # print("STOP: Got HaltInt") # print("") # print("CPU STATE:") # print(cpu.state()) # pass # break # print("painted_once =", painted_once) # print("paints_count =", paints_count) # print("len(painted) =", len(painted)) # if __name__ == "__main__": # amplifiers = [] # program = intcode.read_file('code.txt') # cpu = intcode.CPU(code=program, input=[1]) # probe_paint_code(cpu) if __name__ == "__main__": amplifiers = [] program = intcode.read_file('code.txt') cpu = intcode.CPU(code=program) robo = robopaint.Robot(cpu=cpu) robo.paint(start_color=robopaint.ColorNum.Black) robo.draw_painted() print(robo.painted_count())
import intcode if __name__ == "__main__": amplifiers = [] program = intcode.read_file('code.txt') cpu = intcode.CPU(code=program, input=[1]) cpu.debug = True cpu.execute() print("output:", cpu.output)
import intcode if __name__ == "__main__": amplifiers = [] program = intcode.read_file('code.txt') cpu = intcode.CPU(code=program, input=[2], max_steps=1_000_000) cpu.execute() print("CPU steps:", cpu.step) # 371205 (~40s on MacbookPro 2018) print("output:", cpu.output)
import intcode if __name__ == "__main__": program = intcode.read_file('code.txt') # print(program) cpu = intcode.CPU(memory=program, input=1) cpu.execute() # print("[0]", cpu.memory[0])
def test_memory_rw(): cpu = intcode.CPU(code=[]) value = 1125899906842624 cpu.write_memory(10000, value) got_value = cpu.read_memory(10000) assert value == got_value
def test_cpu_init(): cpu = intcode.CPU(memory=[], input=[]) assert [] == cpu.output