def main(puzzle_input): computer = Intcode(puzzle_input) computer.run_program() part1 = sum([ 1 for i in range(2, len(computer.output), 3) if computer.output[i] == 2 ]) computer = Intcode(puzzle_input) computer.memory[0] = 2 score = 0 while not computer.finished: computer.output.clear() computer.run_program() output = computer.output for i in range(0, len(output), 3): #X=-1, Y=0 -> third is score if output[i] == -1 and output[i + 1] == 0: score = output[i + 2] else: #3 is a horizontal paddle tile. The paddle is indestructible. if output[i + 2] == 3: paddle_pos = output[i] #4 is a ball tile. The ball moves diagonally and bounces off objects. elif output[i + 2] == 4: ball_pos = output[i] if paddle_pos > ball_pos: computer.input.append(-1) elif paddle_pos < ball_pos: computer.input.append(1) else: computer.input.append(0) return part1, score
def amp_to_thruster(phase_set, i_set): # Handles amp chaining, returns [signal, [phase_order]] resultant_set = [0, []] possible_phases = permute(phase_set) for phases in possible_phases: amps = [] temp_result = 0 halted = False for phase in phases: temp_amp = Computer(i_set.copy(), amp_inputs=[phase, temp_result], pause_on_output=True) temp_amp.run_program() temp_result = int(temp_amp.output) amps.append(temp_amp) i = 0 while not halted: amps[i].run_program(amp_inputs=[temp_result]) halted = amps[i].halted if not halted: # print(f'amp output: {amps[i].output} - halted? {amps[i].halted}') temp_result = int(amps[i].output) i += 1 if i == len(amps): i = 0 # Reset and loop # print(f'halted? {halted}') if temp_result > resultant_set[0]: # print(f'New record: {temp_result} using set {phases}') resultant_set = [temp_result, phases] return resultant_set
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) # Feed instructions instructions = [ "OR A T", # Check that A, B or C has a hole "AND B T", "AND C T", "NOT T J", # If any of ABC is a hole, set JUMP "AND D J", # but only if 4th spot is free # "WALK", ] for instruction in instructions: for data_input in ascii_to_data(instruction): computer.set_input(data_input) computer.set_input(ord("\n")) computer.run_program() if len(computer.output_buffer) > 100: print(data_to_ascii(computer.output_buffer)) else: print(data_to_ascii(computer.output_buffer[:-1])) print(computer.output_buffer[-1])
def test_add_opcode_mixed_1(): computer = Intcode([1001, 5, 6, 0, 99, 10, 15], None) computer.run_program() if computer.program[0] == 16: assert True else: assert False
def test_mul_opcode_position(): computer = Intcode([2, 5, 6, 0, 99, 10, 15], None) computer.run_program() if computer.program[0] == 150: assert True else: assert False
def main(puzzle_input): part1 = 0 for phaseSettings in itertools.permutations(range(5)): prev_output = [0] for phaseSetting in phaseSettings: computer = Intcode(puzzle_input) computer.input = [phaseSetting, prev_output[0]] computer.run_program() part1 = max(part1, computer.output[0]) prev_output = computer.output part2 = 0 computer_count = 5 for phaseSettings in itertools.permutations(range(5, 10)): computers = [Intcode("0") for _ in range(computer_count)] for i in range(computer_count): computers[i].memory = computer.memory.copy() computers[i].output = [phaseSettings[i]] for i in range(computer_count): computers[i].input = computers[i - 1].output computers[0].input.append(0) while computers[0].finished == False: for i in range(computer_count): computers[i].run_program() part2 = max(part2, computers[-1].output[0]) return part1, part2
def part1(part_input): print("PART1") GRID_SIZE = 50 grid = [[0 for i in range(GRID_SIZE)] for j in range(GRID_SIZE)] initial_memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] last_point = (0, 0) for j in range(len(grid)): for i in range(len(grid[0])): memory = initial_memory[:] computer = Intcode(memory, input_buffer, output_buffer) computer.set_input(i) computer.set_input(j) computer.run_program() grid[j][i] = computer.output_buffer.pop() if grid[j][i] == 1: last_point = (i, j) print(sum([sum(row) for row in grid])) return last_point
def test_mul_opcode_immediate(): computer = Intcode([1102, 5, 6, 0, 99, 10, 15], None) computer.run_program() if computer.program[0] == 30: assert True else: assert False
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) computer.run_program() output_ascii = list(map(chr, computer.output_buffer)) output_grid = "".join(output_ascii).split("\n") # Detect intersections calibration_sum = 0 for j in range(1, len(output_grid) - 1): for i in range(1, len(output_grid[j]) - 1): if output_grid[j][i] != "#": continue if (output_grid[j][i - 1] == "#" and output_grid[j][i + 1] == "#" and output_grid[j - 1][i] == "#" and output_grid[j + 1][i] == "#"): calibration_sum += i * j print(calibration_sum)
def run_program(puzzle_input, noun, verb): computer = Intcode(puzzle_input) computer.memory[1] = noun computer.memory[2] = verb computer.run_program() return computer.memory[0]
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) # Initialize the droid on an open spot nodes = {} nodes[(0, 0)] = Node(0, 0, 1) droid = nodes[(0, 0)] # Run the program until the robot has finished mapping the whole area while True: movement_command = None current_unexplored = droid.get_unexplored_directions() # If we find a non-explored neighbor, navigate there for test_dir in current_unexplored: movement_command = test_dir break # Check if we need to backtrack if len(current_unexplored) == 0 or movement_command is None: backtrack_command = droid.get_backtrack_movement() if backtrack_command is not None: movement_command = backtrack_command # If the movement command is still None, every path has been checked if movement_command is None: break # Run the program computer.input_buffer.append(movement_command) computer.run_program() output = computer.output_buffer.pop(0) next_position = apply_direction(droid.position, movement_command) if next_position not in nodes: nodes[next_position] = Node(next_position[0], next_position[1], output, droid) # Update the grid's neighbour relations update_neighbors(nodes) if output != 0: droid = nodes[next_position] # Find the shortest path to the oxygen system # Starting from the droid's current position (at the starting position) # do a A* search updating the depth of all nodes droid.set_depth(0) for k, v in nodes.items(): if v.value == 2: print(v.depth) break return nodes
def test_mul_opcode_mixed_2(): computer = Intcode([102, 5, 6, 0, 99, 10, 15], None) computer.run_program() if computer.program[0] == 75: assert True else: print(computer.program[0]) assert False
def position_in_beam(initial_memory, input_buffer, output_buffer, position): memory = initial_memory[:] computer = Intcode(memory, input_buffer, output_buffer) computer.set_input(position[0]) computer.set_input(position[1]) computer.run_program() return computer.output_buffer.pop() == 1
def manual_game(puzzle_input): computer = Intcode(puzzle_input) while not computer.finished: computer.run_program() computer.print_output() print(get_doors(computer.get_output_string())) print(get_items(computer.get_output_string())) computer.add_ascii_input(input()) computer.output.clear() return None, None
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [1] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) computer.run_program() print(computer.output_buffer[0])
def main(puzzle_input): computer = Intcode(puzzle_input) computer.input.append(1) computer.run_program() part1 = computer.output[0] computer = Intcode(puzzle_input) computer.input.append(2) computer.run_program() part2 = computer.output[0] return part1, part2
def main(puzzle_input): computer = Intcode(puzzle_input) computer.input = [1] computer.run_program() part1 = computer.output[-1] computer = Intcode(puzzle_input) computer.input = [5] computer.run_program() part2 = computer.output[0] return part1, part2
def main(puzzle_input): computer = Intcode(puzzle_input) computer.run_program() grid = [] inner = [] for c in computer.output: if c == 10: if len(inner) > 0: grid.append(inner) inner = [] else: inner.append(chr(c)) #print(chr(c), end = '') part1 = 0 for x in range(1, len(grid[0]) - 1): for y in range(1, len(grid) - 1): if grid[y][x] == "#" and all( grid[y + yy][x + xx] == "#" for (xx, yy) in [(0, -1), (1, 0), (0, 1), (-1, 0)]): part1 += x * y for x in range(len(grid[0])): for y in range(len(grid)): if grid[y][x] in "^v<>": pos = x + y * 1j direction = {"^": -1j, "v": 1j, "<": -1, ">": 1}[grid[y][x]] break commands = find_commands(pos, direction, grid) functions = find_functions(commands, []) main_routine = create_main_routine(commands, functions) program_input = [] add_function(program_input, main_routine) for function in functions: add_function(program_input, ",".join(map(str, function))) add_function(program_input, "n") #add_function(program_input, "A,B,A,B,A,C,A,C,B,C") #add_function(program_input, "R,6,L,10,R,10,R,10") #add_function(program_input, "L,10,L,12,R,10") #add_function(program_input, "R,6,L,12,L,10") #add_function(program_input, "n") computer = Intcode(puzzle_input) computer.memory[0] = 2 computer.input = program_input computer.run_program() part2 = computer.output[-1] return part1, part2
def part2(part_input): print("PART2") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] # Set the coin counter memory[0] = 2 computer = Intcode(memory, input_buffer, output_buffer) grid = [[0 for i in range(WIDTH)] for j in range(HEIGHT)] # Run one step to get the paddle and ball positions computer.run_program() parse_output(computer, grid) paddle = [0, 0] ball = [0, 0] score = 0 while True: if sum(map(lambda x: x.count(2), grid)) == 0: break # Update ball and paddle positions for j in range(len(grid)): for i in range(len(grid[j])): if grid[j][i] == 4: ball = [i, j] elif grid[j][i] == 3: paddle = [i, j] # Check which direction to move the paddle if ball[0] == paddle[0]: computer.input_buffer.append(0) elif ball[0] < paddle[0]: computer.input_buffer.append(-1) else: computer.input_buffer.append(1) # Run the program computer.run_program() score = parse_output(computer, grid) # Print the grid # print_grid(grid) print(score)
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) grid = [[0 for i in range(WIDTH)] for j in range(HEIGHT)] computer.run_program() parse_output(computer, grid) print(sum(map(lambda x: x.count(2), grid)))
def manual_game(puzzle_input): computer = Intcode(puzzle_input) computer.memory[0] = 2 score = 0 tiles = {} while not computer.finished: computer.output.clear() computer.run_program() output = computer.output for i in range(0, len(output), 3): #X=-1, Y=0 -> third is score if output[i] == -1 and output[i + 1] == 0: score = output[i + 2] else: #0 is an empty tile. No game object appears in this tile. if output[i + 2] == 0: char = " " #1 is a wall tile. Walls are indestructible barriers. elif output[i + 2] == 1: char = "#" #2 is a block tile. Blocks can be broken by the ball. elif output[i + 2] == 2: char = "*" #3 is a horizontal paddle tile. The paddle is indestructible. elif output[i + 2] == 3: char = "-" #4 is a ball tile. The ball moves diagonally and bounces off objects. elif output[i + 2] == 4: char = "O" tiles[(output[i], output[i + 1])] = char print("Score:", score) for y in range(max([x for x, _ in tiles.keys()]) + 1): for x in range(max([y for _, y in tiles.keys()]) + 1): if (x, y) in tiles: print(tiles[(x, y)], end='') print("") user_input = input() if user_input == "a": computer.input.append(-1) if user_input == "d": computer.input.append(1) if user_input == " ": computer.input.append(0) return None, None
def part2(part_input): print("PART2") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) # Active mode # computer.set_memory(0, 2) computer.run_program() output_ascii = list(map(chr, computer.output_buffer)) output_grid = "".join(output_ascii).split("\n") for row in output_grid: print(row)
def part2(part_input): print("PART2") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) # Feed instructions instructions = [ # Part 1 "OR A T", # Check that A, B or C has a hole "AND B T", "AND C T", "NOT T J", # If any of ABC is a hole, set JUMP "AND D J", # but only if 4th spot is free # Part 2 # Jump only if we can jump immediately (H), # or after 1 step (E and I), # or if 2nd step is possible too (E and F) # -> # H or (E and I) or (E and F) -> # H or (E and (I or F)) "OR I T", "OR F T", "AND E T", "OR H T", "AND T J", # "RUN", ] for instruction in instructions: for data_input in ascii_to_data(instruction): computer.set_input(data_input) computer.set_input(ord("\n")) computer.run_program() if len(computer.output_buffer) > 100: print(data_to_ascii(computer.output_buffer)) else: print(data_to_ascii(computer.output_buffer[:-1])) print(computer.output_buffer[-1])
def main(puzzle_input): computer = Intcode(puzzle_input) program_input = [] add_function(program_input, "NOT C J") add_function(program_input, "AND D J") add_function(program_input, "NOT A T") add_function(program_input, "OR T J") add_function(program_input, "WALK") computer.input = program_input computer.run_program() for c in computer.output: if c >= 256: part1 = c break # ABC[D]EFG[H]I program_input = [] # Hole in A or B or C add_function(program_input, "NOT A J") add_function(program_input, "NOT B T") add_function(program_input, "OR T J") add_function(program_input, "NOT C T") add_function(program_input, "OR T J") # Ground in D and (H or (E and I)) add_function(program_input, "AND D J") add_function(program_input, "OR I T") add_function(program_input, "AND E T") add_function(program_input, "OR H T") add_function(program_input, "AND T J") add_function(program_input, "RUN") computer = Intcode(puzzle_input) computer.input = program_input computer.run_program() for c in computer.output: if c >= 256: part2 = c break return part1, part2
def calculate_paint(puzzle_input, paint): xmin = ymin = float("inf") xmax = ymax = -float("inf") pos = 0 facing = -1j computer = Intcode(puzzle_input) while not computer.finished: computer.output.clear() computer.input.append(paint[pos]) computer.run_program() paint[pos] = computer.output[0] facing *= (1j if computer.output[1] == 1 else -1j) pos += facing xmin = min(xmin, pos.real) xmax = max(xmax, pos.real) ymin = min(ymin, pos.imag) ymax = max(ymax, pos.imag) return int(xmin), int(xmax), int(ymin), int(ymax)
def main(puzzle_input): network = [] for address in range(50): computer = Intcode(puzzle_input) computer.input.append(address) computer.run_program() network.append(computer) part1 = False previous_nat_y = 0 while True: is_idle = True for address in range(50): computer = network[address] if len(computer.input) == 0: computer.input.append(-1) else: is_idle = False computer.run_program() for index in range(0, len(computer.output), 3): if computer.output[index] == 255: nat_value = (computer.output[index + 1], computer.output[index + 2]) if not part1: part1 = nat_value[1] else: target = network[computer.output[index]] target.input.append(computer.output[index + 1]) target.input.append(computer.output[index + 2]) computer.output.clear() if is_idle: if nat_value[1] == previous_nat_y: part2 = previous_nat_y break else: previous_nat_y = nat_value[1] network[0].input.append(nat_value[0]) network[0].input.append(nat_value[1]) return part1, part2
def part1(part_input): print("PART1") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) while True: computer.run_program() print(data_to_ascii(computer.output_buffer)) command = input() if command == "exit": return data = ascii_to_data(command) for code in data: computer.set_input(code) computer.set_input(ord("\n"))
def part2(part_input): print("PART2") memory = parse_input_file(part_input) input_buffer = [] output_buffer = [] computer = Intcode(memory, input_buffer, output_buffer) grid = [[0 for i in range(100)] for j in range(100)] robot_pos = (len(grid) // 2, len(grid) // 2) grid[robot_pos[1]][robot_pos[0]] = 1 robot_dir = 0 dir_lookup = [(0, -1), (1, 0), (0, 1), (-1, 0)] visited = set() while True: step_x, step_y = robot_pos step_input = grid[step_y][step_x] input_buffer.append(step_input) exit_code = computer.run_program() if exit_code is None: break next_color = output_buffer.pop(0) next_dir = output_buffer.pop(0) visited.add(robot_pos) grid[step_y][step_x] = next_color next_dir = next_dir * 2 - 1 robot_dir = (robot_dir + next_dir) % 4 move_offset = dir_lookup[robot_dir] robot_pos = (robot_pos[0] + move_offset[0], robot_pos[1] + move_offset[1]) print(len(visited)) for row in grid: row_str = ['.' if item == 0 else '#' for item in row] print(''.join(row_str))
def main(puzzle_input): part1 = 0 for y in range(50): for x in range(50): computer = Intcode(puzzle_input) computer.input = [x, y] computer.run_program() part1 += computer.output[0] left = 0 right = [] y = 5 while True: for x in range(left, left + 100): computer = Intcode(puzzle_input) computer.input = [x, y] computer.run_program() if computer.output[0] == 1: left = x break if len(right) == 0: right.append(left) for x in range(right[-1], right[-1] + 100): computer = Intcode(puzzle_input) computer.input = [x, y] computer.run_program() if computer.output[0] == 0: right.append(x - 1) break if len(right) > 100: if right[-100] - 99 >= left: part2 = left * 10000 + y - 99 break y += 1 return part1, part2
def main(puzzle_input): #north (1), south (2), west (3), and east (4). dir_input = { ( 0,-1): 1, ( 0, 1): 2, (-1, 0): 3, ( 1, 0): 4, } open_stack = list(dir_input.keys()) area = defaultdict(lambda : -1) pos = (0, 0) area[pos] = 1 computer = Intcode(puzzle_input) while len(open_stack) > 0: pathList = astar.astar(area, pos, open_stack.pop())[1:] for path in pathList: if path in open_stack: open_stack.remove(path) direction = dir_input[(path[0] - pos[0], path[1] - pos[1])] computer.output.clear() computer.input.append(direction) computer.run_program() area[path] = computer.output[0] #0: The repair droid hit a wall. Its position has not changed. if computer.output[0] == 0: pathList.clear() #1: The repair droid has moved one step in the requested direction. elif computer.output[0] == 1: pos = path #2: The repair droid has moved one step in the requested direction; its new position is the location of the oxygen system. elif computer.output[0] == 2: oxygen_pos = path pos = path for test_dir in [(0, -1), (0, 1), (-1, 0), (1, 0)]: test_pos = (pos[0] + test_dir[0], pos[1] + test_dir[1]) if area[test_pos] == -1 and test_pos not in open_stack: open_stack.append(test_pos) #printGrid(area, pos) part1 = len(astar.astar(area, (0, 0), oxygen_pos)) - 1 next_open_set = set() next_open_set.add(oxygen_pos) closed_set = set() part2 = -1 while len(next_open_set) > 0 and len(next_open_set) < 2000: part2 += 1 open_set = next_open_set next_open_set = set() for pos in open_set: closed_set.add(pos) for test_dir in [(0, -1), (0, 1), (-1, 0), (1, 0)]: test_pos = (pos[0] + test_dir[0], pos[1] + test_dir[1]) if area[(test_pos[0], test_pos[1])] <= 0: continue if test_pos in closed_set or test_pos in open_set or test_pos in next_open_set: continue next_open_set.add(test_pos) return part1, part2