summaryrefslogtreecommitdiffstats
path: root/elevator.py
blob: 4a60eceaced0a9b61933f31460bac7a71d224eb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3

from enum import Enum

class Elevator:
	def __init__(self, e_id, floor, goal):
		self.id = e_id
		self.floor = floor
		self.goal = goal
		self.dropoffs = []

	def direction(self):
		if self.goal is None:
			return None
		if self.goal > self.floor:
			return Direction.UP
		else:
			return Direction.DOWN

	def dropoff(self, floor):
		if floor in self.dropoffs:
			assert self.goal is not None
			return
		assert floor != self.floor

		if self.goal is None:
			self.goal = floor
			self.dropoffs.append(floor)
		else:
			direction = self.direction()
			if direction == Direction.UP:
				if floor > self.goal:
					self.goal = floor
				self.dropoffs.append(floor)
				self.dropoffs.sort()
			elif direction == Direction.DOWN:
				if floor < self.goal:
					self.goal = floor
				self.dropoffs.append(floor)
				self.dropoffs.sort(reverse=True)

	def __repr__(self):
		attrs = ', '.join('%s=%s' % t for t in self.__dict__.items())
		return 'Elevator(%s)' % attrs

class Direction(Enum):
	UP = 1
	DOWN = 2

class ElevatorControlSystem:
	def __init__(self, num_elevators):
		self.elevators = {i: Elevator(i, 1, None) for i in range(num_elevators)}
		self.pickup_requests = []

	def pickup(self, floor, direction):
		self.pickup_requests.append((floor, direction))

	def dropoff(self, elevator_id, floor):
		self.elevators[elevator_id].dropoff(floor)

	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

		# move elevators to requested floors
		for elevator in self.elevators.values():
			if elevator.goal is not None:
				if elevator.goal > elevator.floor:
					elevator.floor += 1
				elif elevator.goal < elevator.floor:
					elevator.floor -= 1
				# check dropoffs and goal after moving
				if elevator.dropoffs and elevator.dropoffs[0] == elevator.floor:
					elevator.dropoffs = elevator.dropoffs[1:]
				if elevator.goal == elevator.floor:
					elevator.goal = None

if __name__ == '__main__':
	ecs = ElevatorControlSystem(2)
	print(' '*4, ecs.elevators)

	print('requesting pickup on floor 2 down')
	ecs.pickup(2, Direction.DOWN)
	ecs.step()
	print(' '*4, ecs.elevators)

	print('requesting dropoff on floor 1 and pickup on floor 1 up')
	ecs.dropoff(0, 1)
	ecs.pickup(1, Direction.UP)
	ecs.step()
	print(' '*4, ecs.elevators)

	print('requesting dropoff on floor 3')
	ecs.dropoff(1, 3)
	ecs.step()
	print(' '*4, ecs.elevators)

	print('requesting pickup on floor 2 up')
	ecs.pickup(2, Direction.UP)
	ecs.step()
	print(' '*4, ecs.elevators)