THE ACTUAL CONTRACT
Start with behaviour, not a class diagram
The problem creates fixed compact, regular, and large inventories. A motorcycle tries those categories in that order; a car tries regular and then large; a truck can use only large. Within the first compatible category, allocation must return the lowest free numeric suffix.
State that changes
Free spot suffixes by category and the assigned spot for each parked vehicle.
State that does not change
Constructed capacities, category compatibility, and generated spot identities.
Deliberate exclusions
Billing, floors, reservations, persistence, waiting, timeouts, and concurrency.
Those exclusions matter. Adding a payment service, ticket hierarchy, or lock strategy at this point consumes time without satisfying another line of the contract.
STATE MODEL
Translate the contract into invariants
Before naming classes, write the conditions that must remain true after every operation. They provide a direct way to review the implementation and to locate corruption when a sequence fails.
- 01
One assignment
A vehicle ID is absent or points to exactly one spot; it can never occupy two.
- 02
One spot state
Every spot is either in its category's free pool or assigned to one vehicle, never both.
- 03
Paired mutation
A successful park removes one free spot and creates one assignment; unpark reverses both changes.
- 04
No mutation on rejection
Duplicate parking, a full compatible inventory, and missing departure preserve every assignment and count.
- 05
Validation first
Invalid input raises before duplicate or missing-state checks, so existing state cannot change the error contract.
REPRESENTATION
Choose structures from the operations
| Concern | Smallest useful representation | Reason |
|---|---|---|
| Compatibility | Ordered category list per vehicle type | The only variation is lookup order. |
| Free spots | Minimum-ordered suffixes per category | Allocation and released-spot reuse must choose the lowest number. |
| Assignments | Map from vehicle ID to category and suffix | Duplicate, locate, and unpark all begin with the vehicle ID. |
| Availability | Free-pool size | The query needs no separate counter that can drift. |
| Validation | Small boundary functions | Every argument must be rejected before state inspection. |
Tempting model
Vehicle and Spot hierarchies, factories for both, and one mutable object per parking space.
Contract-shaped model
Three ordered free pools, one assignment map, and a compatibility table.
A hierarchy becomes useful when subtypes own different behaviour. Here, vehicle types only select a category order. Encoding that fact as data is smaller and makes a policy change visible in one place.
PAPER TEST
Walk one sequence before writing methods
For a lot with two compact spots, one regular spot, and one large spot, the first public sequence produces this trace:
park("m1", MOTORCYCLE) -> C-1
park("m2", MOTORCYCLE) -> C-2
park("car1", CAR) -> R-1
park("car2", CAR) -> L-1
park("truck1", TRUCK) -> ""
unpark("car1") -> true
park("m3", MOTORCYCLE) -> R-1This short trace exercises category priority, lowest suffixes, fallback, full rejection, release, and reuse. If the chosen representation cannot explain every line without special cases, revise it before implementation.
75-MINUTE BUILD
Implement in an order that exposes mistakes early
This is a build order for this contract, not a universal interview clock. Each checkpoint leaves something executable instead of postponing the primary flow until the final minutes.
Extract
Copy the compatibility order, return values, validation rules, and exclusions into short notes.
Model
Choose the three ordered free pools and the vehicle-to-spot assignment map.
Construct
Validate capacities, generate suffixes, and implement argument validation before state access.
Park
Handle validation, duplicate rejection, category fallback, lowest suffix, and paired mutation.
Complete
Implement unpark, locate, and availability from the same state model.
Prove
Run the allocation sequence, then duplicate, reuse, full-lot, and missing-vehicle cases.
In a 90-minute round, use the remaining time for the interviewer’s extension and cleanup. Do not spend it creating abstractions that the contract still does not need.
FOLLOW-UP CHANGES
Show where a new requirement would land
“Make allocation order configurable.”
Replace the fixed compatibility table with an injected policy. The free pools and assignment map do not change because the state transition is the same; only category selection varies.
“Now calls may overlap.”
The original problem is explicitly sequential. For concurrent calls, the pool removal and assignment write in park must become one atomic operation; protecting the two structures independently can still double-assign a spot or lose capacity.
This is the extensibility signal worth demonstrating: identify the boundary that changes, and preserve the parts whose reason to change is different.
PUBLIC TEST EVIDENCE
Rejection paths reveal whether the model is coherent
Successful parking is only half of the contract. The public cases also check that rejected and repeated operations leave the lot in a state that later operations can still use.
| Sequence | Observed result | State evidence |
|---|---|---|
| Park the same ID again as another type | Returns an empty string | The original R-1 assignment and counts remain unchanged. |
| Unpark the same ID twice | true, then false | R-1 is released exactly once. |
| Park after successful departure | The ID receives C-1 | Reentry may use a different valid vehicle type. |
| Park a motorcycle in a full compatible lot | Returns an empty string | Every availability count remains zero. |
| Locate or unpark an unknown ID | Empty string or false | No assignment is created as a side effect. |
These checks are more diagnostic than adding another successful park. They distinguish a paired state transition from code that updates a pool, map, or counter on only one branch.
FINAL REVIEW
Review the implementation against the contract
- Capacities are validated before any spot inventory is created.
- Vehicle IDs and enum-like strings are validated before assignment lookup.
- A duplicate park call preserves the original spot and every free-pool size.
- A full-lot rejection changes neither assignments nor availability.
- Unpark returns the released suffix to the correct ordered pool.
- A released low suffix is selected before a higher free suffix.
- Locate and availability queries never mutate state.
- No code exists for billing, floors, waiting, persistence, or concurrency.
At this point, every important choice can be traced back to a requirement and demonstrated with an operation sequence. That is the design argument; extra patterns and classes would not make it stronger.