11_paintrobot.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/env python3
  2. import sys
  3. from operator import add, mul, lt, eq
  4. def run(p, get_input, memsize=0):
  5. def decode_param(offset):
  6. return p[pc + offset], modes // (10 ** (offset - 1)) % 10
  7. def pload(offset):
  8. param, mode = decode_param(offset)
  9. return param if mode == 1 else p[param + relbase * mode // 2]
  10. def pstore(offset, value):
  11. param, mode = decode_param(offset)
  12. p[param + relbase * mode // 2] = value
  13. opmap = {1: add, 2: mul, 7: lt, 8: eq}
  14. p = p + [0] * memsize
  15. pc = relbase = 0
  16. while p[pc] != 99:
  17. modes, opcode = divmod(p[pc], 100)
  18. if opcode in (1, 2, 7, 8):
  19. pstore(3, opmap[opcode](pload(1), pload(2)))
  20. pc += 4
  21. elif opcode == 3:
  22. pstore(1, get_input())
  23. pc += 2
  24. elif opcode == 4:
  25. yield pload(1)
  26. pc += 2
  27. elif opcode == 5:
  28. pc = pload(2) if pload(1) else pc + 3
  29. elif opcode == 6:
  30. pc = pload(2) if not pload(1) else pc + 3
  31. elif opcode == 9:
  32. relbase += pload(1)
  33. pc += 2
  34. def paint(firmware, color):
  35. robot = run(firmware, lambda: color, 1000)
  36. painted = set()
  37. white = set()
  38. x = y = 0
  39. dx, dy = 0, -1
  40. for make_white in robot:
  41. painted.add((x, y))
  42. (white.add if make_white else white.discard)((x, y))
  43. dx, dy = (-dy, dx) if next(robot) else (dy, -dx)
  44. x += dx
  45. y += dy
  46. color = int((x, y) in white)
  47. return white, len(painted)
  48. def draw(coords):
  49. xmin = min(x for x, y in coords)
  50. xmax = max(x for x, y in coords)
  51. ymin = min(y for x, y in coords)
  52. ymax = max(y for x, y in coords)
  53. grid = [[0] * (xmax - xmin + 1) for y in range(ymin, ymax + 1)]
  54. for x, y in coords:
  55. grid[y - ymin][x - xmin] = 1
  56. for row in grid:
  57. print(''.join(' @'[c] for c in row))
  58. firmware = list(map(int, sys.stdin.read().split(',')))
  59. white, npainted = paint(firmware, 0)
  60. print(npainted)
  61. white, npainted = paint(firmware, 1)
  62. draw(white)