def part1(icode): """ Day 15 part 1 Create an INTCODE INSTANCE, then run it """ ### Method 1: explore the space, hope we do not run out of stack instance = intcode.INSTANCE(icode, lt_inputs_arg=[]) instance.run() assert not instance.outputs assert instance.state == intcode.INSTANCE.READWAIT explore_results = explore(instance, ( 0, 0, ), set(), set(), False) ###################################################################### ###################################################################### ### Method 1: explore the space, hope we do not run out of stack instance = intcode.INSTANCE(icode, lt_inputs_arg=[]) instance.run() assert not instance.outputs assert instance.state == intcode.INSTANCE.READWAIT wall_results = wall_follower(instance) ###################################################################### ###################################################################### return ( dict(explore_results=bfs15(*explore_results), wall_results=bfs15(*wall_results)), explore_results, wall_results, )
def run_07_part2(lt_phases, input_signal_arg=0): """ Day 7 part 2: amplifiers in series with phases and inputs, feedback last instance to first, one pass each """ global icode ### Get length of phases of, and indices into, list N = len(lt_phases) R = range(N) ### Create an INTCODE INSTANCE stage for each input phase instances = [ intcode.INSTANCE(icode, lt_inputs_arg=lt_phases[i:i + 1]) for i in R ] ### Add initial input signal to first stage instances[0].add_input_data(input_signal_arg) ### Cascade stages, including feedback from last to first for i in R: instances[i].make_cascade(instances[(i + 1) % N]) while True: ### Set result counts finis = 0 readwaits = 0 for instance in instances: ### Loop over each stage instance.run() ### Update stage result counts if instance.state == intcode.INSTANCE.READWAIT: readwaits += 1 elif instance.state == intcode.INSTANCE.FINI: finis += 1 else: assert dict()['{0},{1}'.format(readwaits, finis)] ### Continue if all stages expect to read another input if N == readwaits: for instance in instances: assert len(instance.inputs) >= instance.input_ptr continue assert 0 == readwaits assert N == finis break return instances[-1].outputs[-1]
def part1(icode): """ Day 13 part 1 Create an INTCODE INSTANCE, then run it; this will draw the board by loading (X,Y,Type) triplets into list instance.outputs """ instance = intcode.INSTANCE(icode, lt_inputs_arg=[]) instance.run() assert intcode.INSTANCE.FINI == instance.state return instance.outputs
def part1(icode): """ Day 15 part 1 Create an INTCODE INSTANCE, then run it """ instance = intcode.INSTANCE(icode) instance.run() lt_rows = list() lt_row = list() result, height = 0, 0 for i in instance.outputs: c = chr(i) assert c in sall if cnl == c: if not lt_row: break if lt_rows: assert width == len(lt_row) else: width = len(lt_row) lt_rows.append(lt_row) height = len(lt_rows) lt_row = list() else: pos = len(lt_row) if c in sdirs: start_xy = pos, height elif 1 < height and chash == c: c2up = lt_rows[-2][pos] c1up = lt_rows[-1][pos - 1:pos + 2] if (chash == c2up) and (chash3 == c1up): result += ((height - 1) * pos) lt_row.append(c) assert not lt_row return dict(result=result, start_xy=start_xy, lt_rows=lt_rows, instance_state=instance.state)
def part2(icode): """ Day 13 part 2 Repeatedly run program. As each round is lost because ball passes the paddle, find where that occurred and add joystick movement as needed via dt_i """ ### dt_: dict of joystick non-zero moves ### dt_scores: dict of counts of scores, for detecting infinite loops dt_i, dt_scores = dict(), dict() ### Initial input: do nothing inputs = [0] while True: ### Create an INTCODE INSTANCE, put two quarters into coin slot ### (memory location 2), add one input datum to dt_i, then run program instance = intcode.INSTANCE(icode, lt_inputs_arg=[]) instance.vm[0] = 2 instance.add_input_data(*inputs) instance.run() ### Save last output pointer Llast = len(instance.outputs) ### If no joystick inputs yet, save initial paddle position if not dt_i: Lo = len(instance.outputs) while True: Lo -= 3 if instance.outputs[Lo + 2] == 3: ### Type 3 is paddle position; save X and Y paddlex, paddley = paddle = instance.outputs[Lo:Lo + 2] paddle_toggle = paddley + paddley - 1 break if do_debug: print( '\n========================================================================' ) print(( 'Start', Llast, instance.outputs[-30:], )) print(dict(paddle=paddle)) ### Run program as long as it is waiting for input ### - If it is not waiting for input, it ended, either because ball ### passed paddle, or all blocks are gone while intcode.INSTANCE.READWAIT == instance.state: Lo = len(instance.outputs) if do_debug: print(( 'Read', Lo, instance.outputs[Llast:], )) Llast = Lo instance.add_input_data(dt_i.get(Lo, 0), state_must_be_init=False) instance.run() if do_debug: print(( 'Endw', dict(state=instance.state), )) x, y, score = instance.outputs[-3:] if -1 == x and 0 == y and score > 0: ### End of successful round: all blocks are gone; pickle outputs ### for play13.py; exit outer [while True] loop with open('13.pickle', 'wb') as fout: pickle.dump(dict(lt_outputs=instance.outputs, dt_inputs=dt_i), fout) ### Return score and outputs return score, instance.outputs ### Copy last 200 output triples list (tail); find where ball exited ### field, add joystick movement to paddle to catch it next time tail = instance.outputs[-600:] ### Variable adjust will be None until a ball position on row ### [paddley] is found; then ad will be a non-zero integer that is ### incremented or decremented for each previous INSTANCE.READWAIT ### occurrence, until it hits zero adjust = None ### Loop until adjust is zero Lo = len(instance.outputs) while (adjust is None) or adjust: ### Get last (x,y,type) triple typ, y, x = tail.pop(), tail.pop(), tail.pop() if typ == 4: ### Triple expresses a ball position if not (adjust is None): ### Variable adjust is non-zero integer; Lo is length of ### instance.outputs for this ball position and when ### INSTANCE.READWAIT occurred in last run ### - Variable extra6 accounts for paddle movement data ### in next run extra6 -= 6 ### - Move paddle at INSTANCE.READWAIT when ### len(instance.outputs) will be (Lo+extra6) delta = adjust > 0 and +1 or -1 adjust -= delta paddlex += delta dt_i[Lo + extra6] = delta if do_debug: print( dict(adjust=adjust, paddlex=paddlex, paddley=paddley, Lo=Lo, Loplus=Lo + extra6, dtnew=dt_i[Lo + extra6])) elif paddley == y: ### Variable adjust is None; initialize joystick variables; ### ball is at x,paddley; paddley is on or above paddle row ### - x is ball position ### - paddlex is paddle position ### - Set adjust to how much paddle must move ### - Add 6 positions per move to account for movement ### of paddle in instance.outputs list during next loop adjust = x - paddlex extra6 = 6 * abs(adjust) if do_debug: print( dict(adjust=adjust, x=x, paddlex=paddlex, extra6=extra6)) sys.stdout.flush() assert adjust ### Decrement output pointer Lo -= 3 if do_debug: Lo = len(instance.outputs) print(( 'Fini', Lo, instance.outputs[Llast:], )) Lo = len(instance.outputs) ### Find last non-zero score score = 0 while (Lo > 10000) and (not score): x, y, typ = instance.outputs[Lo - 3:Lo] if (-1 == x) and (0 == y): score = typ Lo -= 3 if score: ### Keep track of how many times this non-zero score occurred if score in dt_scores: dt_scores[score] += 1 else: dt_scores[score] = 1 ### If it occurred 20 times, adjust paddley parameter that ### controls paddle adjustment above if score and (dt_scores[score] > 19): dt_scores[score] = 0 paddley = paddle_toggle - paddley if do_debug: print(( 'Score', dict(score=score, score_count=dt_scores[score], paddley=paddley), )) assert intcode.INSTANCE.FINI == instance.state sys.stdout.flush()
def run_11(start_color): """ Day 11 part 1 """ global icode ### Create an INTCODE INSTANCE instance = intcode.INSTANCE(icode, lt_inputs_arg=[]) st_whites, xypair, dir, output_ptr = set(), ( 0, 0, ), 0, 0 st_painted_once = set() if start_color == white: st_whites.add(xypair) instance.run() while intcode.INSTANCE.READWAIT == instance.state: Lo = len(instance.outputs) if (Lo - 2) == output_ptr: color, turn = instance.outputs[-2:] output_ptr += 2 if white == color: st_whites.add(xypair) else: st_whites.discard(xypair) st_painted_once.add(xypair) dir = (dir + 4 + (turn and 1 or -1)) % 4 if 0 == dir: xypair = ( xypair[0] + 0, xypair[1] - 1, ) elif 1 == dir: xypair = ( xypair[0] + 1, xypair[1] + 0, ) elif 2 == dir: xypair = ( xypair[0] + 0, xypair[1] + 1, ) else: xypair = ( xypair[0] - 1, xypair[1] + 0, ) else: assert not instance.outputs instance.add_input_data(*[xypair in st_whites and white or black], state_must_be_init=False) instance.run() xwhites, ywhites = zip(*st_whites) xmin = min(xwhites) ymin = min(ywhites) width = 1 + max(xwhites) - xmin height = 1 + max(ywhites) - ymin arr = [[' '] * width for i in range(height)] #print((width,height,xmin,ymin,)) #print((len(arr[0]),len(arr),)) for x, y in st_whites: #print((x,y,)) arr[y - ymin][x - xmin] = '@' return len(st_painted_once), st_whites, '\n'.join( [''.join(row) for row in arr])
def part2(icode): """ Day 15 part 2 """ dt_part1_results = part1(icode) lt_rows = dt_part1_results['lt_rows'] start_xy = dt_part1_results['start_xy'] current_xy = tuple(list(start_xy)) current_c = get_c(lt_rows, current_xy) start_dir = dt_dirs[current_c] current_dir = tuple(list(start_dir)) assert not (current_xy is start_xy) assert not (current_dir is start_dir) linear_steps = 0 lt_commands = list() while True: if do_debug: print( dict(lt_commands_last4=lt_commands[-4:], linear_steps=linear_steps, current_c=current_c, current_xy=current_xy, current_dir=current_dir)) if chash == get_c(lt_rows, current_xy, current_dir): linear_steps += 1 current_xy = move(current_xy, current_dir) current_c = chash continue if 0 < linear_steps: lt_commands.append('{0}'.format(linear_steps)) linear_steps = False for f in ( turn_rt, turn_lt, ): new_dir = f(current_dir) if chash == get_c(lt_rows, current_xy, new_dir): current_dir = new_dir current_xy = move(current_xy, new_dir) linear_steps = 1 current_c = chash lt_commands.append(f is turn_rt and 'R' or 'L') break if do_debug: print( dict(linear_steps=linear_steps, Llt_commands=len(lt_commands))) if linear_steps: continue if lt_commands: break ### Try opposite direction via two left turns current_dir = turn_lt(turn_lt(current_dir)) assert chash == get_c(lt_rows, current_xy, current_dir) lt_commands.extend(list('LL')) s_commands = ','.join(lt_commands) dt_fs = splitter.splitter17(s_commands) keys = sorted(list(dt_fs.keys())) main_routine = s_commands for key in keys: s_value = dt_fs[key] assert 20 > len(s_value) main_routine = main_routine.replace(s_value, key) s_inputs = cnl.join([main_routine] + [dt_fs[key] for key in keys] + ['n', '']) instance = intcode.INSTANCE(icode, lt_inputs_arg=[ord(s) for s in s_inputs]) assert 1 == instance.vm[0] instance.vm[0] = 2 instance.run() rtn = dict(s_commands=s_commands, main_routine=main_routine, Loutputs=len(instance.outputs), lt_result=[v for v in instance.outputs if v < 0 or v > 127]) rtn.update(dt_fs) return rtn, instance.outputs