Browse Source

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
Ashton Charbonneau 5 years ago
parent
commit
14dbbb7688
1 changed files with 97 additions and 76 deletions
  1. 97
    76
      elevator.js

+ 97
- 76
elevator.js View File

@@ -1,32 +1,72 @@
1 1
 eval({
2 2
 	init: function(elevators, floors) {
3 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 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 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 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 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 64
 		// getNextFloor chooses the best destination for an elevator
25 65
 		// when given the index of the elevator, along with all
26 66
 		// destinations, requests, and rest floors.
27 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 71
 			if (requests[UP].size == 0 && requests[DOWN].size == 0 && destinations.size == 0) {
32 72
 				// No people; send to rest floor
@@ -45,50 +85,18 @@ eval({
45 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 92
 		// getClosestElevator takes a floor number and returns the
85 93
 		// index of the closest elevator.
86 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 100
 				newDistance = Math.abs(elevator.currentFloor() - floorNum);
93 101
 				if (newDistance < distance) {
94 102
 					distance = newDistance;
@@ -103,31 +111,33 @@ eval({
103 111
 		// getDirection get the direction (up or down) that an elevator
104 112
 		// will need to travel to get to a specified floor
105 113
 		function getDirection(currentFloor, floorNum) {
106
-			let distance = currentFloor - floorNum;
114
+			const distance = currentFloor - floorNum;
115
+			let direction = IDLE;
116
+
107 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 126
 		// setDirection changes the indicator lights on a specified
117 127
 		// elevator to match the given direction.
118 128
 		function setDirection(elevator, direction) {
119 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,7 +145,7 @@ eval({
135 145
 		// Floors
136 146
 		// ----
137 147
 
138
-		floors.forEach(function (floor) {
148
+		floors.forEach(function(floor) {
139 149
 			floor.on("up_button_pressed", function() {
140 150
 				//console.log("> Up request on floor[" + floor.level + "]");
141 151
 				requests[UP].add(floor.level);
@@ -150,22 +160,20 @@ eval({
150 160
 		// Elevators
151 161
 		// ----
152 162
 
153
-		elevators.forEach(function (elevator, elevatorIndex) {
163
+		elevators.forEach(function(elevator, elevatorIndex) {
154 164
 			// Elevator info and variables
155
-			let destinations = new Set();
156
-
157 165
 			const restFloors = [
158 166
 				elevatorIndex * Math.floor(floorCount / (elevatorCount + 1)),
159 167
 				(elevatorIndex + 1) * Math.floor(floorCount / (elevatorCount + 1)),
160 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 174
 			// Start
167 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 177
 			elevator.goToFloor(nextFloor); // Nearest rest floor
170 178
 
171 179
 			// Idle
@@ -177,9 +185,10 @@ eval({
177 185
 
178 186
 			// Passing
179 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 192
 					elevator.goToFloor(floorNum, true);
184 193
 				}
185 194
 			});
@@ -193,14 +202,26 @@ eval({
193 202
 			// Stopped
194 203
 			elevator.on("stopped_at_floor", function(floorNum) {
195 204
 				//console.log("> elevator[" + elevatorIndex + "] stopped at floor[" + floorNum + "]");
196
-				setDirection(elevator, getDirection(elevator.currentFloor(), nextFloor));
205
+				let isNext = (elevator.currentFloor() == nextFloor);
206
+
197 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 214
 				if (elevator.goingUpIndicator() == true) {
199 215
 					requests[UP].delete(floorNum);
200 216
 				}
217
+
201 218
 				if (elevator.goingDownIndicator() == true) {
202 219
 					requests[DOWN].delete(floorNum);
203 220
 				}
221
+
222
+				if (isNext) {
223
+					elevator.goToFloor(nextFloor);
224
+				}
204 225
 			});
205 226
 		});
206 227
 	},

Loading…
Cancel
Save