22_virus.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/env python3
  2. import sys
  3. class PartOne:
  4. def __init__(self, grid):
  5. self.infected = set()
  6. for y, line in enumerate(grid.split('\n')):
  7. for x, cell in enumerate(line):
  8. if cell == '#':
  9. self.infected.add((y, x))
  10. self.y = y // 2
  11. self.x = x // 2
  12. self.dy = -1
  13. self.dx = 0
  14. def turn_left(self):
  15. self.dy, self.dx = -self.dx, self.dy
  16. def turn_right(self):
  17. self.dy, self.dx = self.dx, -self.dy
  18. def advance(self):
  19. pos = self.y, self.x
  20. if pos in self.infected:
  21. self.infected.remove(pos)
  22. self.turn_right()
  23. infection = False
  24. else:
  25. self.infected.add(pos)
  26. self.turn_left()
  27. infection = True
  28. self.y += self.dy
  29. self.x += self.dx
  30. return infection
  31. CLEAN, FLAGGED, INFECTED, WEAKENED = range(4)
  32. class PartTwo(PartOne):
  33. def __init__(self, grid):
  34. self.nodes = {}
  35. for y, line in enumerate(grid.split('\n')):
  36. for x, cell in enumerate(line):
  37. if cell == '#':
  38. self.nodes[(y, x)] = INFECTED
  39. self.y = y // 2
  40. self.x = x // 2
  41. self.dy = -1
  42. self.dx = 0
  43. def at(self, y, x):
  44. return self.nodes.get((y, x), CLEAN)
  45. def turn_back(self):
  46. self.dy, self.dx = -self.dy, -self.dx
  47. def advance(self):
  48. state = self.at(self.y, self.x)
  49. if state == CLEAN:
  50. self.turn_left()
  51. elif state == INFECTED:
  52. self.turn_right()
  53. elif state == FLAGGED:
  54. self.turn_back()
  55. self.nodes[(self.y, self.x)] = (self.at(self.y, self.x) + 3) % 4
  56. self.y += self.dy
  57. self.x += self.dx
  58. return state == WEAKENED
  59. grid = sys.stdin.read().rstrip()
  60. state = PartOne(grid)
  61. print(sum(int(state.advance()) for i in range(10000)))
  62. state = PartTwo(grid)
  63. print(sum(int(state.advance()) for i in range(10000000)))