elevator.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/env python3
  2. from enum import Enum
  3. class Elevator:
  4. def __init__(self, e_id, floor, goal):
  5. self.id = e_id
  6. self.floor = floor
  7. self.goal = goal
  8. self.dropoffs = []
  9. def direction(self):
  10. if self.goal is None:
  11. return None
  12. if self.goal > self.floor:
  13. return Direction.UP
  14. else:
  15. return Direction.DOWN
  16. def dropoff(self, floor):
  17. if floor in self.dropoffs:
  18. assert self.goal is not None
  19. return
  20. assert floor != self.floor
  21. if self.goal is None:
  22. self.goal = floor
  23. self.dropoffs.append(floor)
  24. else:
  25. direction = self.direction()
  26. if direction == Direction.UP:
  27. if floor > self.goal:
  28. self.goal = floor
  29. self.dropoffs.append(floor)
  30. self.dropoffs.sort()
  31. elif direction == Direction.DOWN:
  32. if floor < self.goal:
  33. self.goal = floor
  34. self.dropoffs.append(floor)
  35. self.dropoffs.sort(reverse=True)
  36. def __repr__(self):
  37. attrs = ', '.join('%s=%s' % t for t in self.__dict__.items())
  38. return 'Elevator(%s)' % attrs
  39. class Direction(Enum):
  40. UP = 1
  41. DOWN = 2
  42. class ElevatorControlSystem:
  43. def __init__(self, num_elevators):
  44. self.elevators = {i: Elevator(i, 1, None) for i in range(num_elevators)}
  45. self.pickup_requests = []
  46. def pickup(self, floor, direction):
  47. self.pickup_requests.append((floor, direction))
  48. def dropoff(self, elevator_id, floor):
  49. self.elevators[elevator_id].dropoff(floor)
  50. def step(self):
  51. # serve pickup requests
  52. free_elevators = list(filter(lambda e: e.goal is None, self.elevators.values()))
  53. while free_elevators and self.pickup_requests:
  54. floor, direction = self.pickup_requests.pop(0)
  55. elevator = min(free_elevators, key=lambda e: abs(e.floor - floor))
  56. elevator.goal = floor
  57. # move elevators to requested floors
  58. for elevator in self.elevators.values():
  59. if elevator.goal is not None:
  60. if elevator.goal > elevator.floor:
  61. elevator.floor += 1
  62. elif elevator.goal < elevator.floor:
  63. elevator.floor -= 1
  64. # check dropoffs and goal after moving
  65. if elevator.dropoffs and elevator.dropoffs[0] == elevator.floor:
  66. elevator.dropoffs = elevator.dropoffs[1:]
  67. if elevator.goal == elevator.floor:
  68. elevator.goal = None
  69. if __name__ == '__main__':
  70. ecs = ElevatorControlSystem(2)
  71. print(' '*4, ecs.elevators)
  72. print('requesting pickup on floor 2 down')
  73. ecs.pickup(2, Direction.DOWN)
  74. ecs.step()
  75. print(' '*4, ecs.elevators)
  76. print('requesting dropoff on floor 1 and pickup on floor 1 up')
  77. ecs.dropoff(0, 1)
  78. ecs.pickup(1, Direction.UP)
  79. ecs.step()
  80. print(' '*4, ecs.elevators)
  81. print('requesting dropoff on floor 3')
  82. ecs.dropoff(1, 3)
  83. ecs.step()
  84. print(' '*4, ecs.elevators)
  85. print('requesting pickup on floor 2 up')
  86. ecs.pickup(2, Direction.UP)
  87. ecs.step()
  88. print(' '*4, ecs.elevators)