# Design a Parking Lot — High-Level & Low-Level Design Interview Problems

Source: https://www.skillbyai.com/en/design-interviews/parking-lot

> Floors, spots, tickets and pricing.

## Requirements and model

Clarify: multiple floors; spot sizes (small, compact, large); vehicles (motorcycle, car, truck) that fit certain sizes; entry issues a ticket, exit computes a fee and frees the spot; display free counts. Model: `ParkingLot` has `Floor`s, each with `ParkingSpot`s; `Vehicle` has a `VehicleType`; `Ticket` records vehicle, spot and entry time. Put spot selection in a `SpotAllocationStrategy` (nearest first, by floor) and fees in a `PricingStrategy`. Concurrency: two entry gates must not assign the same spot, so allocation must be atomic, for example by synchronising on the floor or using a concurrent free-spot queue per size.

## Classic object-oriented designs

Parking lots, elevators and vending machines appear in many LLD rounds because they test modelling, strategy and state.

![Three problems: a parking lot, an elevator system and a vending machine as a state machine.](assets/figures/design-interviews/section-3-map.svg) — Figure 3.1 — Parking lot, elevator and vending machine models.

## Core classes

Java sketch; getters and validation trimmed.

```java
enum SpotSize { SMALL, COMPACT, LARGE }
enum VehicleType { MOTORCYCLE, CAR, TRUCK }

record Vehicle(String plate, VehicleType type) {}
record Ticket(String id, Vehicle vehicle, ParkingSpot spot, java.time.Instant entryTime) {}

class ParkingSpot {
    final String id; final SpotSize size;
    ParkingSpot(String id, SpotSize size) { this.id = id; this.size = size; }
}

class Floor {
    private final java.util.Map<SpotSize, java.util.Deque<ParkingSpot>> free = new java.util.EnumMap<>(SpotSize.class);

    synchronized java.util.Optional<ParkingSpot> take(SpotSize size) {
        java.util.Deque<ParkingSpot> q = free.get(size);
        return (q == null || q.isEmpty()) ? java.util.Optional.empty() : java.util.Optional.of(q.poll());
    }
    synchronized void release(ParkingSpot spot) {
        free.computeIfAbsent(spot.size, s -> new java.util.ArrayDeque<>()).push(spot);
    }
}

interface SpotAllocationStrategy {
    java.util.Optional<ParkingSpot> allocate(java.util.List<Floor> floors, VehicleType type);
}
```

## Map vehicle to allowed sizes

A small table such as CAR -> [COMPACT, LARGE] keeps fitting rules in one place and makes adding a new vehicle type a data change.

**Quiz:** Why make spot allocation atomic?

- [x] So two gates cannot assign the same spot at the same time
- [ ] To speed up fee calculation
- [ ] To avoid needing tickets
- [ ] Because enums are not thread safe

*Answer:* So two gates cannot assign the same spot at the same time. Concurrent entries race for spots.
