11_seats.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. #!/usr/bin/env python3
  2. import sys
  3. FLOOR, EMPTY, OCCUPIED = range(3)
  4. def parse(f):
  5. state = []
  6. for line in f:
  7. state += ['.L#'.index(c) for c in line.rstrip()]
  8. w = len(line.rstrip())
  9. return state, w
  10. def changes(state, w, tolerance, see_far):
  11. h = len(state) // w
  12. def see_occupied(x, y, dx, dy):
  13. x += dx
  14. y += dy
  15. if x < 0 or x >= w or y < 0 or y >= h:
  16. return False
  17. seat = state[y * w + x]
  18. if seat != FLOOR:
  19. return seat == OCCUPIED
  20. return see_far and see_occupied(x, y, dx, dy)
  21. def occupied_nb(i):
  22. y, x = divmod(i, w)
  23. return sum(see_occupied(x, y, dx, dy)
  24. for dx in (-1, 0, 1)
  25. for dy in (-1, 0, 1)
  26. if dx or dy)
  27. for i, seat in enumerate(state):
  28. if seat == EMPTY and occupied_nb(i) == 0:
  29. yield i, OCCUPIED
  30. elif seat == OCCUPIED and occupied_nb(i) >= tolerance:
  31. yield i, EMPTY
  32. def stabilize(state, w, tolerance, see_far):
  33. state = list(state)
  34. changeset = list(changes(state, w, tolerance, see_far))
  35. while changeset:
  36. for i, seat in changeset:
  37. state[i] = seat
  38. changeset[::] = changes(state, w, tolerance, see_far)
  39. return state
  40. state, w = parse(sys.stdin)
  41. print(stabilize(state, w, 4, False).count(OCCUPIED))
  42. print(stabilize(state, w, 5, True).count(OCCUPIED))