浏览代码

Break closest floor ties by floor index

This commit adjusts the way ties are calculated when deciding the
closest floor. Even floors default to going up, and odd floors default
to going down. This changed reduced waiting time a bit, which allows
this code to pass challenges 1-12.
master
父节点
当前提交
14dbbb7688
共有 1 个文件被更改,包括 97 次插入76 次删除
  1. 97
    76
      elevator.js

+ 97
- 76
elevator.js 查看文件

1
 eval({
1
 eval({
2
 	init: function(elevators, floors) {
2
 	init: function(elevators, floors) {
3
 		// Get elevator/building info
3
 		// Get elevator/building info
4
-		let elevatorCount = elevators.length;
5
-		let floorCount    = floors.length;
6
-		let topFloor      = floorCount - 1;
7
-		let bottomFloor   = 0;
4
+		const elevatorCount = elevators.length,
5
+		      floorCount    = floors.length,
6
+		      bottomFloor   = 0,
7
+		      topFloor      = floorCount - 1;
8
 
8
 
9
 		console.clear();
9
 		console.clear();
10
-		console.log("Starting (" + floorCount + " floors; " + elevatorCount + " elevator" + ((floorCount == 1) ? "s" : "") +")...");
10
+		("Starting (" + floorCount + " floors; " + elevatorCount + " elevator" + (floorCount == 1) ? "s" : "" + ")...");
11
 
11
 
12
 		// Direction constants
12
 		// Direction constants
13
-		const UP   = 0;
14
-		const DOWN = 1;
15
-		const IDLE = 2;
13
+		const UP   = 0,
14
+		      DOWN = 1,
15
+		      IDLE = 2;
16
+
17
+		// Rest floor constants
18
+		const LOW  = 0,
19
+		      MED  = 1,
20
+		      HIGH = 2;
16
 
21
 
17
 		// Data structure for floor requests
22
 		// Data structure for floor requests
18
-		let requests = [new Set(), new Set()];
23
+		const requests = [new Set(), new Set()];
19
 
24
 
20
 		// ----
25
 		// ----
21
 		// Functions
26
 		// Functions
22
 		// ----
27
 		// ----
23
 
28
 
29
+		// getClosestFloor takes a floor, a list of floors, an optional
30
+		// list of ignored floors, and an optional direction. It
31
+		// returns the closest floor from that list in the given
32
+		// direction that is not part of the ignored floors list. Ties
33
+		// are broken by even/oddness of the current floor.
34
+		function getClosestFloor(currentFloor, floorList, ignoredFloors = new Set(), direction = IDLE) {
35
+			const isEven = (currentFloor % 2 == 0);
36
+
37
+			let closestFloor = currentFloor,
38
+			    distance     = floorCount,
39
+			    newDistance  = distance;
40
+
41
+			floorList.forEach(function(floorNum) {
42
+				const direction = getDirection(currentFloor, floorNum);
43
+				newDistance = Math.abs(currentFloor - floorNum);
44
+
45
+				if (newDistance < distance && newDistance > 0 && !(ignoredFloors.has(floorNum))) {
46
+					closestFloor = floorNum;
47
+					distance = newDistance;
48
+				} else if (newDistance == distance && !(ignoredFloors.has(floorNum))) {
49
+					if (isEven && direction == UP) {
50
+						closestFloor = floorNum;
51
+					} else if (!isEven && direction == DOWN) {
52
+						closestFloor = floorNum;
53
+					}
54
+				}
55
+			});
56
+
57
+			if (closestFloor != currentFloor) {
58
+				return closestFloor;
59
+			} else {
60
+				throw new Error("No floor in selected direction");
61
+			}
62
+		}
63
+
24
 		// getNextFloor chooses the best destination for an elevator
64
 		// getNextFloor chooses the best destination for an elevator
25
 		// when given the index of the elevator, along with all
65
 		// when given the index of the elevator, along with all
26
 		// destinations, requests, and rest floors.
66
 		// destinations, requests, and rest floors.
27
 		function getNextFloor(elevators, elevatorIndex, destinations, requests, restFloors) {
67
 		function getNextFloor(elevators, elevatorIndex, destinations, requests, restFloors) {
28
-			let elevator = elevators[elevatorIndex];
29
-			let floorNum = restFloors[1];
68
+			let elevator = elevators[elevatorIndex],
69
+			    floorNum = restFloors[MED];
30
 
70
 
31
 			if (requests[UP].size == 0 && requests[DOWN].size == 0 && destinations.size == 0) {
71
 			if (requests[UP].size == 0 && requests[DOWN].size == 0 && destinations.size == 0) {
32
 				// No people; send to rest floor
72
 				// No people; send to rest floor
45
 					console.log("ERROR: Destinations set was empty");
85
 					console.log("ERROR: Destinations set was empty");
46
 				}
86
 				}
47
 			}
87
 			}
48
-			return floorNum;
49
-		}
50
-
51
-		// getClosestFloor takes a floor, a list of floors, an optional
52
-		// list of ignored floors, and an optional direction. It
53
-		// returns the closest floor from that list in the given
54
-		// direction that is not part of the ignored floors list.
55
-		function getClosestFloor(currentFloor, floorList, ignoredFloors = new Set(), direction = IDLE) {
56
-			let closestFloor = currentFloor;
57
-			let distance     = floorCount;
58
-			let newDistance  = distance;
59
-
60
-			floorList.forEach(function(floorNum) {
61
-				switch (direction) {
62
-					case UP:
63
-						newDistance = floorNum - currentFloor;
64
-						break;
65
-					case DOWN:
66
-						newDistance = currentFloor - floorNum;
67
-						break;
68
-					case IDLE:
69
-						newDistance = Math.abs(floorNum - currentFloor);
70
-				}
71
-				if (newDistance < distance && newDistance > 0 && !(ignoredFloors.has(floorNum))) {
72
-					closestFloor = floorNum;
73
-					distance = newDistance;
74
-				}
75
-			});
76
 
88
 
77
-			if (closestFloor != currentFloor) {
78
-				return closestFloor;
79
-			} else {
80
-				throw new Error("No floor in selected direction");
81
-			}
89
+			return floorNum;
82
 		}
90
 		}
83
 
91
 
84
 		// getClosestElevator takes a floor number and returns the
92
 		// getClosestElevator takes a floor number and returns the
85
 		// index of the closest elevator.
93
 		// index of the closest elevator.
86
 		function getClosestElevator(floorNum) {
94
 		function getClosestElevator(floorNum) {
87
-			let closestElevator = 0;
88
-			let distance        = floorCount;
89
-			let newDistance     = distance;
95
+			let closestElevator = 0,
96
+			    distance        = floorCount,
97
+			    newDistance     = distance;
90
 
98
 
91
-			elevators.forEach(function (elevator, elevatorIndex) {
99
+			elevators.forEach(function(elevator, elevatorIndex) {
92
 				newDistance = Math.abs(elevator.currentFloor() - floorNum);
100
 				newDistance = Math.abs(elevator.currentFloor() - floorNum);
93
 				if (newDistance < distance) {
101
 				if (newDistance < distance) {
94
 					distance = newDistance;
102
 					distance = newDistance;
103
 		// getDirection get the direction (up or down) that an elevator
111
 		// getDirection get the direction (up or down) that an elevator
104
 		// will need to travel to get to a specified floor
112
 		// will need to travel to get to a specified floor
105
 		function getDirection(currentFloor, floorNum) {
113
 		function getDirection(currentFloor, floorNum) {
106
-			let distance = currentFloor - floorNum;
114
+			const distance = currentFloor - floorNum;
115
+			let direction = IDLE;
116
+
107
 			if (distance > 0 || currentFloor == topFloor) {
117
 			if (distance > 0 || currentFloor == topFloor) {
108
-				return DOWN;
109
-			} else if (distance < 0 || currentFloor == 0) {
110
-				return UP;
111
-			} else {
112
-				return IDLE;
118
+				direction = DOWN;
119
+			} else if (distance < 0 || currentFloor == bottomFloor) {
120
+				direction = UP;
113
 			}
121
 			}
122
+
123
+			return direction;
114
 		}
124
 		}
115
 
125
 
116
 		// setDirection changes the indicator lights on a specified
126
 		// setDirection changes the indicator lights on a specified
117
 		// elevator to match the given direction.
127
 		// elevator to match the given direction.
118
 		function setDirection(elevator, direction) {
128
 		function setDirection(elevator, direction) {
119
 			switch (direction) {
129
 			switch (direction) {
120
-				case UP:
121
-					elevator.goingUpIndicator(true);
122
-					elevator.goingDownIndicator(false);
123
-					break;
124
-				case DOWN:
125
-					elevator.goingUpIndicator(false);
126
-					elevator.goingDownIndicator(true);
127
-					break;
128
-				default:
129
-					elevator.goingUpIndicator(true);
130
-					elevator.goingDownIndicator(true);
130
+			case UP:
131
+				elevator.goingUpIndicator(true);
132
+				elevator.goingDownIndicator(false);
133
+				break;
134
+			case DOWN:
135
+				elevator.goingUpIndicator(false);
136
+				elevator.goingDownIndicator(true);
137
+				break;
138
+			default:
139
+				elevator.goingUpIndicator(true);
140
+				elevator.goingDownIndicator(true);
131
 			}
141
 			}
132
 		}
142
 		}
133
 
143
 
135
 		// Floors
145
 		// Floors
136
 		// ----
146
 		// ----
137
 
147
 
138
-		floors.forEach(function (floor) {
148
+		floors.forEach(function(floor) {
139
 			floor.on("up_button_pressed", function() {
149
 			floor.on("up_button_pressed", function() {
140
 				//console.log("> Up request on floor[" + floor.level + "]");
150
 				//console.log("> Up request on floor[" + floor.level + "]");
141
 				requests[UP].add(floor.level);
151
 				requests[UP].add(floor.level);
150
 		// Elevators
160
 		// Elevators
151
 		// ----
161
 		// ----
152
 
162
 
153
-		elevators.forEach(function (elevator, elevatorIndex) {
163
+		elevators.forEach(function(elevator, elevatorIndex) {
154
 			// Elevator info and variables
164
 			// Elevator info and variables
155
-			let destinations = new Set();
156
-
157
 			const restFloors = [
165
 			const restFloors = [
158
 				elevatorIndex * Math.floor(floorCount / (elevatorCount + 1)),
166
 				elevatorIndex * Math.floor(floorCount / (elevatorCount + 1)),
159
 				(elevatorIndex + 1) * Math.floor(floorCount / (elevatorCount + 1)),
167
 				(elevatorIndex + 1) * Math.floor(floorCount / (elevatorCount + 1)),
160
 				(elevatorIndex + 2) * Math.floor(floorCount / (elevatorCount + 1))
168
 				(elevatorIndex + 2) * Math.floor(floorCount / (elevatorCount + 1))
161
 			];
169
 			];
162
 
170
 
163
-			// Next primary stop
164
-			let nextFloor = restFloors[0];
171
+			let destinations = new Set(),
172
+			    nextFloor = restFloors[LOW];
165
 
173
 
166
 			// Start
174
 			// Start
167
 			setDirection(elevator, UP); // Starts on the ground floor, must be going up
175
 			setDirection(elevator, UP); // Starts on the ground floor, must be going up
168
-			console.log("> Elevator[" + elevatorIndex + "] rest floors are " + restFloors[0] + ", " + restFloors[1] + ", and " + restFloors[2] + ". Starting at " + restFloors[0] + ".");
176
+			console.log("> Elevator[" + elevatorIndex + "] rest floors are " + restFloors[LOW] + ", " + restFloors[MED] + ", and " + restFloors[HIGH] + ". Starting at " + restFloors[LOW] + ".");
169
 			elevator.goToFloor(nextFloor); // Nearest rest floor
177
 			elevator.goToFloor(nextFloor); // Nearest rest floor
170
 
178
 
171
 			// Idle
179
 			// Idle
177
 
185
 
178
 			// Passing
186
 			// Passing
179
 			elevator.on("passing_floor", function(floorNum, direction) {
187
 			elevator.on("passing_floor", function(floorNum, direction) {
180
-				if (destinations.has(floorNum)
181
-				  || (elevator.loadFactor() < 1 && elevator.destinationDirection() == "up" && requests[UP].has(floorNum))
182
-				  || (elevator.loadFactor() < 1 && elevator.destinationDirection() == "down" && requests[DOWN].has(floorNum))) {
188
+				if (destinations.has(floorNum) ||
189
+				   (elevator.loadFactor() < 1 &&
190
+				   (elevator.destinationDirection() == "up" && requests[UP].has(floorNum)) ||
191
+				   (elevator.destinationDirection() == "down" && requests[DOWN].has(floorNum)))) {
183
 					elevator.goToFloor(floorNum, true);
192
 					elevator.goToFloor(floorNum, true);
184
 				}
193
 				}
185
 			});
194
 			});
193
 			// Stopped
202
 			// Stopped
194
 			elevator.on("stopped_at_floor", function(floorNum) {
203
 			elevator.on("stopped_at_floor", function(floorNum) {
195
 				//console.log("> elevator[" + elevatorIndex + "] stopped at floor[" + floorNum + "]");
204
 				//console.log("> elevator[" + elevatorIndex + "] stopped at floor[" + floorNum + "]");
196
-				setDirection(elevator, getDirection(elevator.currentFloor(), nextFloor));
205
+				let isNext = (elevator.currentFloor() == nextFloor);
206
+
197
 				destinations.delete(floorNum);
207
 				destinations.delete(floorNum);
208
+
209
+				if (isNext) {
210
+					nextFloor = getNextFloor(elevators, elevatorIndex, destinations, requests, restFloors);
211
+					setDirection(elevator, getDirection(elevator.currentFloor(), nextFloor));
212
+				}
213
+
198
 				if (elevator.goingUpIndicator() == true) {
214
 				if (elevator.goingUpIndicator() == true) {
199
 					requests[UP].delete(floorNum);
215
 					requests[UP].delete(floorNum);
200
 				}
216
 				}
217
+
201
 				if (elevator.goingDownIndicator() == true) {
218
 				if (elevator.goingDownIndicator() == true) {
202
 					requests[DOWN].delete(floorNum);
219
 					requests[DOWN].delete(floorNum);
203
 				}
220
 				}
221
+
222
+				if (isNext) {
223
+					elevator.goToFloor(nextFloor);
224
+				}
204
 			});
225
 			});
205
 		});
226
 		});
206
 	},
227
 	},

正在加载...
取消
保存