summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorraylu <lurayl@gmail.com>2016-02-22 21:38:26 -0800
committerraylu <lurayl@gmail.com>2016-02-22 21:59:35 -0800
commite6bb1edfc2f16c7d75d7f849bef08397e7a968d2 (patch)
tree05a013ba4c6e2fa6f37bc1c3add7766290945d9b
parentc4bfe29b8fb90ea805201f6b741d757bc49f59d4 (diff)
downloadelevator-master.tar.xz
send the best elevator for the jobHEADmaster
-rwxr-xr-xelevator.py88
1 files changed, 79 insertions, 9 deletions
diff --git a/elevator.py b/elevator.py
index 4a60ece..8ab5517 100755
--- a/elevator.py
+++ b/elevator.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
+import copy
from enum import Enum
class Elevator:
@@ -7,9 +8,11 @@ class Elevator:
self.id = e_id
self.floor = floor
self.goal = goal
+ self.pickup_direction = None # the direction we're handling pickup requests for
self.dropoffs = []
def direction(self):
+ ' the direction the elevator is currently moving in '
if self.goal is None:
return None
if self.goal > self.floor:
@@ -22,12 +25,14 @@ class Elevator:
assert self.goal is not None
return
assert floor != self.floor
+ assert self.pickup_direction is None
if self.goal is None:
self.goal = floor
self.dropoffs.append(floor)
else:
direction = self.direction()
+ # TODO: handle opposite direction dropoffs
if direction == Direction.UP:
if floor > self.goal:
self.goal = floor
@@ -39,6 +44,42 @@ class Elevator:
self.dropoffs.append(floor)
self.dropoffs.sort(reverse=True)
+ def estimate_pickup_time(self, floor, direction):
+ # while dropping off, can handle requests in same elevator dir in between current and goal
+ # while picking up, can handle requests in same dir as request dir
+ # when requested floor is in dir of elevator
+ our_dir = self.direction()
+ if our_dir is None:
+ return abs(floor - self.floor)
+
+ if self.dropoffs: # we are moving and have dropoffs
+ if our_dir == Direction.UP:
+ if self.floor <= floor and direction == our_dir:
+ return floor - self.floor
+ else:
+ to_goal = self.goal - self.floor
+ to_request = abs(self.goal - floor)
+ return to_goal + to_request
+ else:
+ if self.floor >= floor and direction == our_dir:
+ return self.floor - floor
+ else:
+ to_goal = self.floor - self.goal
+ to_request = abs(self.goal - floor)
+ return to_goal + to_request
+ else: # we are moving to pick up a request
+ assert self.pickup_direction is not None
+ if our_dir == Direction.UP:
+ if self.floor <= floor <= self.goal and direction == self.pickup_direction:
+ return floor - self.floor
+ else:
+ return float('inf')
+ else:
+ if self.floor >= floor >= self.goal and direction == self.pickup_direction:
+ return self.floor - floor
+ else:
+ return float('inf')
+
def __repr__(self):
attrs = ', '.join('%s=%s' % t for t in self.__dict__.items())
return 'Elevator(%s)' % attrs
@@ -60,11 +101,25 @@ class ElevatorControlSystem:
def step(self):
# serve pickup requests
- free_elevators = list(filter(lambda e: e.goal is None, self.elevators.values()))
- while free_elevators and self.pickup_requests:
- floor, direction = self.pickup_requests.pop(0)
- elevator = min(free_elevators, key=lambda e: abs(e.floor - floor))
- elevator.goal = floor
+ for floor, direction in copy.copy(self.pickup_requests):
+ min_time = float('inf')
+ min_elevator = None
+ for elevator in self.elevators.values():
+ time = elevator.estimate_pickup_time(floor, direction)
+ if time < min_time:
+ min_time = time
+ min_elevator = elevator
+ if min_elevator:
+ # only handle the request now if the min_elevator is right here or doing nothing. if
+ # it's moving, min_time should improve by at least 1 per step. handle this request
+ # later (in case some other elevator finishes a dropoff and can pickup sooner)
+ if min_time == 0:
+ assert min_elevator.floor == floor
+ self.pickup_requests.remove((floor, direction))
+ elif min_elevator.goal is None:
+ min_elevator.goal = floor
+ min_elevator.pickup_direction = direction
+ self.pickup_requests.remove((floor, direction))
# move elevators to requested floors
for elevator in self.elevators.values():
@@ -77,7 +132,7 @@ class ElevatorControlSystem:
if elevator.dropoffs and elevator.dropoffs[0] == elevator.floor:
elevator.dropoffs = elevator.dropoffs[1:]
if elevator.goal == elevator.floor:
- elevator.goal = None
+ elevator.goal = elevator.pickup_direction = None
if __name__ == '__main__':
ecs = ElevatorControlSystem(2)
@@ -94,12 +149,27 @@ if __name__ == '__main__':
ecs.step()
print(' '*4, ecs.elevators)
- print('requesting dropoff on floor 3')
+ print('requesting dropoff on floor 5 and 3')
+ ecs.dropoff(1, 5)
ecs.dropoff(1, 3)
ecs.step()
print(' '*4, ecs.elevators)
- print('requesting pickup on floor 2 up')
- ecs.pickup(2, Direction.UP)
+ print('requesting pickup on floor 3 up')
+ ecs.pickup(3, Direction.UP)
+ ecs.step()
+ print(' '*4, ecs.elevators)
+
+ print('requesting pickup on floor 5 down')
+ ecs.pickup(5, Direction.DOWN)
+ ecs.step()
+ print(' '*8, ecs.pickup_requests)
+ print(' '*4, ecs.elevators)
+
+ ecs.step()
+ print(' '*8, ecs.pickup_requests)
+ print(' '*4, ecs.elevators)
+
ecs.step()
+ print(' '*8, ecs.pickup_requests)
print(' '*4, ecs.elevators)