def main(display=False): program = Intcode() program.load_from_file('inputs/day_13_input.txt') program.memory[0] = 2 # Hack to play for free x_ball = None x_paddle = None score = 0 joystick = 0 monitor = Display(screendict) while not program.ishalted: while not program.iswaiting and not program.ishalted: program.step() while program.output_buffer: x = program.output() y = program.output() v = program.output() if x == -1 and y == 0: score = v else: if v == 3: x_paddle = x if v == 4: x_ball = x monitor.update({(x, y): v}) if (x_ball is not None) and (x_paddle is not None): joystick = (x_ball > x_paddle) - (x_ball < x_paddle) program.input(joystick) program.step() # Clear the waiting condition if display: monitor.show(legend='SCORE: {0}'.format(score)) print("\nFinal score: {0}\n".format(score)) return score
def paint_hull(hull, coordinates): # Circular list with main directions in a cartesian frame (CW order) # Default (starting) direction is the first, to the North directions = deque([(0, 1), (1, 0), (0, -1), (-1, 0)]) def turn_left(): directions.rotate(1) def turn_right(): directions.rotate(-1) def direction(): return directions[0] program = Intcode() program.load_from_file('inputs/day_11_input.txt') while True: # Provide panel color as input try: program.input(hull[coordinates]) except KeyError: program.input(0) # All panels start black # Let's wait for the two outputs while (len(program.output_buffer) < 2) and not program.ishalted: program.step() if program.ishalted: break # First output is the colour colour = program.output() hull[coordinates] = colour # Second output is the rotation rotation = program.output() if rotation == 0: turn_left() elif rotation == 1: turn_right() else: raise ValueError() coordinates = advance(coordinates, direction()) return hull, coordinates
def main(display=False): """ We'll only use LEFT rotations, since R = LLL, so we'll recover it later. We'll also work with the map spread out on a single line In this configuration, L-R is -/+ 1 and U-D is -/+ N, (N is a line length) First we trace the scaffold with the strategy "keep going forward until you can only turn, then turn - all until you can only backtrack". Then we try to compress the obtained command sequence, and give the result to the Intcode computer to process. """ # Prepare the map lines = map_scaffolding() N = len(lines[0]) mapstr = ''.join(lines) # Circular list with main directions in CW order (Up Right Down Left) directions = deque([-N, +1, +N, -1]) def turn_left(): directions.rotate(+1) # This "rotates the robot" def front(): return directions[0] # This indicates "the direction the robot faces" def next_tile(position, last_visited): """ Returns true if the tile in front of the robot is a valid scaffold tile We make sure that it's not a recently visited scaffold, so we're not just backtracking, hence the "valid" """ try: new_position = position + front() if mapstr[new_position] == '#' and new_position != last_visited: # Also check that we're not crossing the L or R borders if not (((position % N) == 0 and front() == -1) or ((position % N) == N - 1 and front() == +1)): return True except IndexError: pass return False # PATHFINDING & COMMAND BUILDING # Find the robot robot_pos = re.search(r'[^\.\#]', mapstr).start() last_visited = None robot_dir = {'^': -N, '>': +1, 'v': +N, '<': -1}[mapstr[robot_pos]] # Align reference system, since front() by default is pointing Up while front() != robot_dir: turn_left() # Build command sequence as a list commands = [] while True: rotation_timeout = 0 while not next_tile(robot_pos, last_visited) and rotation_timeout < 4: turn_left() commands.append('L') rotation_timeout = rotation_timeout + 1 if rotation_timeout == 4: break # We're spinning in circles, nowhere left to go... counter = 0 while next_tile(robot_pos, last_visited): last_visited = robot_pos robot_pos = robot_pos + front() counter = counter + 1 commands.append(str(counter)) # Cut away last Ls while spinning in cicles and convert LLL into R while commands[-1] == 'L': commands.pop(-1) replace_sublist(commands, ['L', 'L', 'L'], ['R']) # Compress commands symbols = ['A', 'B', 'C'] sequence, functions = compress(commands, symbols, maxlen=20) # RUNNING THE INTCODE PROGRAM program = Intcode() program.load_from_file('inputs/day_17_input.txt') program.memory[0] = 2 # Manual override video_feed = {True: 'y', False: 'n'}[display] # Build program input program_input = '{0}\n'.format(sequence) for s in symbols: program_input = program_input + '{0}\n'.format(functions[s]) program_input = program_input + '{0}\n'.format(video_feed) for x in program_input: program.input(ord(x)) # Run the program if display: # Live video feed screen_buffer = '' while not program.ishalted: program.step() if program.output_buffer: screen_buffer += chr(program.output()) # TODO: handle values outside of chr range if screen_buffer[-2:] == '\n\n': Display.clear() print(screen_buffer, end='') screen_buffer = '' dust = ord(screen_buffer[-1]) # Reconstruct dust from last output else: # Output only program.execute() dust = program.output_buffer[-1] # Output print("\nFound a solution with sequence: {0}".format(sequence)) for symbol in symbols: print("{0}: {1}".format(symbol, functions[symbol])) print("\nTotal dust collected: {0}\n".format(dust)) return dust