def part2(data): code = Code(data) code[0] = 2 # free play exe = Executor(code) ball = 0 paddle = 0 def track_ball(): # simple strategy - paddle tracks ball if ball < paddle: return -1 elif ball > paddle: return 1 return 0 exe.input_next = track_ball for x, y, t in zip(exe.runner, exe.runner, exe.runner): if (x, y) == (-1, 0): print("\033[1;45H%10d" % t) continue if t == 4: ball = x elif t == 3: paddle = x print("\033[%d;%dH%s" % (y + 1, x + 1, ch[t])) print("\033[40;0H")
def part1(data): exe = Executor(Code(data)) it = iter(exe.complete()) tiles = list(zip(it, it, it)) mx = max(x for x, _, _ in tiles) + 1 my = max(y for _, y, _ in tiles) + 1 board = np.zeros((my, mx)) for x, y, i in tiles: board[y, x] = i return (board == 2).sum()
def test_intcode(): assert Executor( Code('109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99') ).complete() == [ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99 ] assert Executor(Code('1102,34915192,34915192,7,4,7,99,0')).complete() == [ 1219070632396864 ] assert Executor( Code('104,1125899906842624,99')).complete() == [1125899906842624]
def part2(data): grid = robot(Executor(code), initial=1) paint = np.array([(pos[1], pos[0]) for pos, colour in grid.items() if colour]) size = paint.max(axis=0) + [1, 1] panel = np.full(size, '.') panel[paint[:, 0], paint[:, 1]] = '#' return '\n'.join(''.join(row) for row in panel)
def part1(data): code = Code(data) computers = [Executor(code, [i, -1]) for i in range(50)] while True: for i, computer in enumerate(computers): addr, x, y = computer.executen(3) if addr == 255: return y if addr is not None: computers[addr].inputs.extend([x, y]) return None
def feedback(code, phases): output = 0 amps = [Executor(code) for phase in phases] for amp, phase in zip(amps, phases): amp.inputs.append(phase) while True: for amp in amps: # amp.inputs.append(output) try: output = amp.execute(output) except StopIteration: return output return output
def part2(data): code = Code(data) exe = Executor(code) output = ''.join(map(chr, exe.complete())) code[0] = 2 exe = Executor(code) # manually devised sequence! main = 'A,B,A,B,A,C,B,C,A,C' a = 'R,4,L,10,L,10' b = 'L,8,R,12,R,10,R,4' c = 'L,8,L,8,R,10,R,4' live = 'n' #'y' for line in (main, a, b, c, live): exe.inputs.extend(map(ord, line)) exe.inputs.append(10) for ch in exe.runner: if ch > 255: return ch print(chr(ch), end='')
def walk(data): exe = Executor(Code(data)) grid = {} queue = [Point(0, 0, [])] draw(0, 0, '.') breadth = True while True: p = queue.pop(0) # check each direction for i in (1, 2, 3, 4): nx = p.x + dx[i] ny = p.y + dy[i] if (nx, ny) in grid: continue # try this direction resp = exe.execute(i) assert resp in (0, 1, 2) if resp == 0: # wall, unchanged grid[nx, ny] = '#' draw(nx, ny, '#') elif resp in (1, 2): if resp == 2: part1 = len(p.walk) + 1 breadth = False c = '.' if resp == 1 else 'O' grid[nx, ny] = c draw(nx, ny, c) # moved - add to explore list if resp == 1: # Odd, if you explore from the oxygen we get an # assertion failure (ie position is off). if breadth: queue.append(Point(nx, ny, p.walk + [i])) else: queue.insert(0, Point(nx, ny, p.walk + [i])) # retrace step assert exe.execute(rev[i]) == 1 if not queue: break # optimisation: return to common point in next point np = queue[0] i = prefix(np.walk, p.walk) for j in reversed(p.walk[i:]): assert exe.execute(rev[j]) == 1 for j in np.walk[i:]: assert exe.execute(j) == 1 return part1, grid
def part1(data): code = Code(data) exe = Executor(code) def point(x, y): exe = Executor(code) return exe.execute(x, y) def search(start, end, step): edge = start for row in range(start, end, step): try: edge = next(x for x in range(edge, end, step) if point(x, row)) yield edge except StopIteration: continue lefts = list(search(0, 50, 1)) rights = list(search(49, -1, -1)) return sum(rights) - sum(lefts) + len(lefts)
def part2(data): code = Code(data) exe = Executor(code) # ABCDEFGHI # 0________ = 1 ~A # _0_______ = 1 ~B # ___1_____ = 1 & D # __0__0___ = 1 ~C & ~F # __0____1_ = 1 ~C & H lines = [ # Jump if C and F are both holes (~C & ~F) 'NOT C J', 'NOT F T', 'AND T J', # Jump if C is a hole and H is not a hole (~C & H) 'NOT C T', 'AND H T', 'OR T J', # Jump if B is a hole (~B) 'NOT B T', 'OR T J', # Jump if A is a hole (~A) 'NOT A T', 'OR T J', # Walk if D is a hole (D) 'AND D J', 'RUN', ] for line in lines: exe.inputs.extend(map(ord, line)) exe.inputs.append(10) for ch in exe.runner: if ch > 255: return ch print(chr(ch), end='')
def part2(data): code = Code(data) computers = [Executor(code, [i, -1]) for i in range(50)] nat = [] ys = set() while True: blocked = 0 for i, computer in enumerate(computers): addr, x, y = computer.executen(3) if addr is None: blocked += 1 continue if addr == 255: nat = [x, y] else: computers[addr].inputs.extend([x, y]) if blocked == 50: if nat[1] in ys: return nat[1] ys.add(nat[1]) computers[0].inputs.extend(nat)
def part1(data): code = Code(data) exe = Executor(code) # 0001 = 1 # 0010 = X # 0011 = X # 0100 = X # 0101 = 1 # 0110 = X # 0111 = 1 # 1000 = 0 # 1001 = 1 # 1010 = 0 # 1011 = 1 # 1100 = 0 # 1101 = 1 # 1110 = 0 # 1111 = 0 # ~A | (~B & D) | (~C & D) lines = [ 'NOT A J', 'NOT B T', 'AND D T', 'OR T J', 'NOT C T', 'AND D T', 'OR T J', 'WALK' ] for line in lines: exe.inputs.extend(map(ord, line)) exe.inputs.append(10) for ch in exe.runner: if ch > 255: return ch print(chr(ch), end='')
def point(x, y): exe = Executor(code) return exe.execute(x, y)
def part1(data): return len(robot(Executor(code)))
def part2(code): return Executor(code).complete(2)
def part1(data): exe = Executor(Code(data)) output = ''.join(map(chr, exe.complete())) return part1_map(output)
def __init__(self, data): self.exe = Executor(Code(data))
def part1(code): return Executor(code).complete(1)
def chain(code, phases): output = 0 for phase in phases: prog = Executor(code) output = prog.execute(phase, output) return output