Course contents

LLD problem — Parking Lot

Sign in to run this lab and save your progress

Learn

Before you start

Parking Lot is the most-asked design interview problem in the world. Every major product company has asked it. It's small enough to finish in an interview, big enough to reveal design skill.

Signals to spot

Two design signals are baked into the requirements. See if you can spot them before reading further.

Signal 1: "Adding a new vehicle type shouldn't rewrite existing code."

Signal 2: "Changing the fee rules should touch one place."

Both point at patterns from modules 1-3. Which ones? Write your answer in design.md before implementing.

What separates a strong answer from a weak one

Weak: hardcodes vehicle types with if vtype == "bike": ... in three places (park, fit, fee). Passes the tests. Fails the interviewer's follow-up questions.

Strong: builds a per-vehicle-type object that owns its own spot-fit list and its own fee rate. Adding an "electric-car" is one new class + one registration. The test verifies this.

The tests can't tell these two apart — both pass on behavior. That's why design.md matters. Your reasoning is what an interviewer will judge.

The rules question

"No spot holds two vehicles" sounds trivial. Then how do you handle:

  • A caller passes a ticket_id that doesn't exist. Do you crash? Silently do nothing? Raise an explicit error?
  • The same ticket_id gets unparked twice. Second call — what happens?

The tests pin these to raises ValueError. Your design.md should say WHERE this rule is enforced (e.g., "the active tickets dict is checked on every unpark; missing key raises").

Signals to look for in every design problem going forward

Read requirements with these questions in mind:

  1. What changes over time? (State signal.)
  2. What gets added or removed as the system grows? (Factory / Registry / Strategy signal.)
  3. What must always be true? (A rule → where do you enforce it?)
  4. What algorithm has multiple valid versions? (Strategy signal.)
  5. What tree-shaped data appears? (Composite signal.)

Every problem in this module can be answered by walking this checklist and picking the patterns that fire.

Your task

Design a parking lot management system.

The problem

A parking lot has a fixed set of spots of three sizes: compact, regular, large.

Vehicles come in three types:

  • bike — fits in any spot (compact / regular / large)
  • car — fits in regular or large
  • truck — fits in large only

Operations:

  • park(vehicle, arrival_time) — assign the SMALLEST spot that fits, return a ticket (dict with keys ticket_id, plate, spot_size, arrival_time). If no spot fits, return None.
  • unpark(ticket_id, departure_time) — release the spot, return the fee.
  • available(size) — return the number of free spots of the given size.

Fee rules:

  • bike → ₹10 per started hour
  • car → ₹30 per started hour
  • truck → ₹100 per started hour
  • Any partial hour counts as a full hour. Minimum charge: one hour.
  • Time is in integer minutes. Hour = 60 minutes.
  • ceil((departure - arrival) / 60) — but at least 1.

Setup:

lot = ParkingLot(compact=3, regular=5, large=2)
ticket = lot.park(Vehicle("KA-01-1234", "car"), arrival_time=100)
# ticket = {"ticket_id": ..., "plate": "KA-01-1234",
#           "spot_size": "regular", "arrival_time": 100}
fee = lot.unpark(ticket["ticket_id"], departure_time=190)
# 190 - 100 = 90 minutes → 2 hours (partial counts) → 60 rupees

Requirement-gathering questions

We've made these choices; your design must respect them:

  1. Assignment policy? — Smallest fitting spot. A bike goes to compact before regular before large.
  2. What if no fitting spot exists but a bigger one is free? — For MVP, a car cannot occupy a large spot if a regular is free (smallest-fit only). If NO smaller/equal spot fits, we DO promote — a truck can only fit large. Actually simpler: a vehicle takes the SMALLEST size that fits. If a car can fit in regular OR large, it takes regular when available; when regular is full but large has room, it takes large.
  3. Multi-lot / multi-floor? — Single lot, single floor. No hierarchy.
  4. Concurrency? — Single-threaded MVP. No locks.
  5. Payment / receipt? — Fee returned as an int (rupees). No payment method modeled.

Design goals

  • Adding a new vehicle type (e.g., electric-car with charging spots) should not rewrite existing code.
  • Changing the fee policy (say, per-15-min instead of per-hour) should touch ONE place.
  • Invariants: no spot holds two vehicles; no vehicle occupies two spots; unpark of an unknown ticket must not corrupt state.

Your task

Write design.md explaining your choices, then implement main.py with this public API:

from main import ParkingLot, Vehicle

lot = ParkingLot(compact=int, regular=int, large=int)
vehicle = Vehicle(plate=str, vtype=str)   # vtype: "bike"|"car"|"truck"
ticket = lot.park(vehicle, arrival_time=int)  # returns dict or None
fee = lot.unpark(ticket_id=str, departure_time=int)  # int
free = lot.available(size=str)  # "compact"|"regular"|"large" -> int

Unpark of an unknown or already-released ticket raises ValueError.

Read the tests before you start — the exact ticket shape and fee formula are pinned there.

Click Submit to run the tests. Both design.md and main.py are graded.

Starter files

Preview only — open the lab to edit and run.

files_dir
02-parking-lot-starter