소스 검색

Solve 2019 day 15

Taddeus Kroes 6 년 전
부모
커밋
81204197c3
2개의 변경된 파일117개의 추가작업 그리고 0개의 파일을 삭제
  1. 117 0
      2019/15_repair.py
  2. 0 0
      2019/input/15

+ 117 - 0
2019/15_repair.py

@@ -0,0 +1,117 @@
+#!/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))

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
2019/input/15


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.