cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 187 of 218
Ideas this builds on
Low-level design187 / 218

Design an elevator controller

Picture

One simulated car starts at floor 0 and receives a fixed batch requesting floors 2 and 5. A nearest-stop policy chooses the next destination. Movement and door transitions remain the controller’s responsibility.

Predict

Why keep choosing the next stop separate from moving one floor?

Walk through the small example

Scheduling policies can change without rewriting the safety-related state transitions in the simulation. The controller should still close doors before moving and open them only at a served stop.

Mental model and complete Python solution

Pending floors form a set, so repeated button presses do not duplicate stops. Each tick first closes open doors; otherwise it selects the nearest pending floor, moves one level, and opens on arrival. Ties favor the lower floor. The example serves finite batches; continuous nearby requests could starve a distant request. Passenger direction, capacity, emergencies, multiple cars, and physical interlocks are explicitly not modeled.

What the function promises: Floors are integers 0..top. request adds a stop; tick returns (floor, doors_open). This is a single-car educational simulator, never suitable for real elevator control.

class Elevator:
    def __init__(self, top, start=0):
        if type(top) is not int or top < 0 or not 0 <= start <= top:
            raise ValueError("Invalid floor range")
        self.top, self.floor = top, start
        self.pending = set()
        self.doors_open = False

    def request(self, floor):
        if type(floor) is not int or not 0 <= floor <= self.top:
            raise ValueError("Floor out of range")
        self.pending.add(floor)

    def tick(self):
        if self.doors_open:
            self.doors_open = False
        elif self.pending:
            target = min(self.pending, key=lambda f: (abs(f-self.floor), f))
            if target != self.floor:
                self.floor += 1 if target > self.floor else -1
            if self.floor == target:
                self.pending.remove(target)
                self.doors_open = True
        return self.floor, self.doors_open

car = Elevator(5)
car.request(2)
car.request(5)
car.request(2)
assert car.tick() == (1, False)
assert car.tick() == (2, True)
assert car.tick() == (2, False)
assert car.tick() == (3, False)
assert car.tick() == (4, False)
assert car.tick() == (5, True)
assert not car.pending

Work and storage: Each scheduling decision scans P pending floors: O(P) time, O(P) storage. More advanced indexes and policies can reduce work or improve fairness, but must follow stated requirements.

When to recognize it: Separate selecting the next stop from moving the car and opening its doors.

Check before applying it: This is not a safety-certified controller. Real elevators require hardware interlocks, fault handling, passenger direction, and multi-car dispatch.

Change one rule

We add many cars and continuous hall requests with travel direction. Is one shared nearest-floor set sufficient?

See what changes

No. Separate hall calls from car destinations, define dispatch ownership and fairness, and coordinate assignments. A directional sweep may reduce reversal, while multi-car dispatch introduces another policy layer.

Connect

Swap the rule, not the whole feature: Nearest-stop, FIFO, and directional sweep are different scheduling policies.

Make legal actions visible: Movement and door states constrain legal actions.