#!/usr/bin/env python3 import sys from collections import defaultdict, deque from operator import add, mul, lt, eq from time import sleep def run(p, get_input, memsize=0): def decode_param(offset): return p[pc + offset], modes // (10 ** (offset - 1)) % 10 def pload(offset): param, mode = decode_param(offset) return param if mode == 1 else p[param + relbase * mode // 2] def pstore(offset, value): param, mode = decode_param(offset) p[param + relbase * mode // 2] = value opmap = {1: add, 2: mul, 7: lt, 8: eq} p = p + [0] * memsize pc = relbase = 0 while p[pc] != 99: modes, opcode = divmod(p[pc], 100) if opcode in (1, 2, 7, 8): pstore(3, opmap[opcode](pload(1), pload(2))) pc += 4 elif opcode == 3: pstore(1, get_input()) pc += 2 elif opcode == 4: yield pload(1) pc += 2 elif opcode == 5: pc = pload(2) if pload(1) else pc + 3 elif opcode == 6: pc = pload(2) if not pload(1) else pc + 3 elif opcode == 9: relbase += pload(1) pc += 2 NORTH, SOUTH, EAST, WEST = range(1, 5) WALL, SPACE, OXYGEN, UNKOWN = range(4) DX = [0, 0, -1, 1] DY = [-1, 1, 0, 0] def draw(mapped, robot): if '-v' not in sys.argv: return def draw_pos(pos): return 'D' if pos == robot else '#.O '[mapped.get(pos, UNKOWN)] minx = min(x for x, y in mapped) maxx = max(x for x, y in mapped) miny = min(y for y, y in mapped) maxy = max(y for y, y in mapped) print('\033c', end='') for y in range(miny, maxy + 1): print(''.join(draw_pos((x, y)) for x in range(minx, maxx + 1))) sleep(.001) def map_area(program): reverse_dir = [SOUTH, NORTH, WEST, EAST] pos = 0, 0 direction = NORTH control = run(program, lambda: direction, 0) mapped = {pos: SPACE} path = [(NORTH, pos)] oxygen_distance = None def pick_direction(): x, y = pos for d in (NORTH, SOUTH, EAST, WEST): newpos = x + DX[d - 1], y + DY[d - 1] if newpos not in mapped: return False, (d, newpos) return True, path.pop() while len(path): backtrack, (direction, newpos) = pick_direction() status = next(control) mapped[newpos] = status if status != WALL: if not backtrack: path.append((reverse_dir[direction - 1], pos)) pos = newpos if status == OXYGEN: oxygen_distance = len(path) - 1 draw(mapped, pos) return oxygen_distance, mapped def spread_oxygen(mapped): frontier = set(pos for pos, status in mapped.items() if status == OXYGEN) minutes = -1 while frontier: newfrontier = set() for x, y in frontier: mapped[(x, y)] = OXYGEN for d in range(4): nb = x + DX[d], y + DY[d] if mapped[nb] == SPACE: newfrontier.add(nb) minutes += 1 frontier = newfrontier draw(mapped, None) return minutes program = list(map(int, sys.stdin.readline().split(','))) oxygen_distance, mapped = map_area(program) print(oxygen_distance) print(spread_oxygen(mapped))