Rust Parking Lot Manager
This challenge involves building a robust parking lot management system in Rust. You'll create data structures and functions to handle vehicle entries, exits, and status inquiries, simulating the core operations of a real-world parking facility. This exercise will help you practice Rust's ownership, borrowing, and error handling mechanisms.
Problem Description
You need to design and implement a ParkingLot struct in Rust that can manage a fixed number of parking spots. The system should support the following operations:
- Parking a Vehicle: Register a vehicle entering the parking lot.
- Unparking a Vehicle: Register a vehicle leaving the parking lot.
- Checking Availability: Determine the number of available parking spots.
- Listing Occupied Spots: Retrieve a list of all vehicles currently parked.
Key Requirements:
- Fixed Capacity: The parking lot has a fixed capacity that is set upon initialization.
- Unique Vehicle Identifiers: Each vehicle is identified by a unique string (e.g., license plate).
- Spot Management: The system must track which spots are occupied and by which vehicle.
- Error Handling: The system should gracefully handle invalid operations, such as trying to park a vehicle when the lot is full, or unparking a vehicle that is not present.
- Data Structures: Choose appropriate Rust data structures to efficiently store and manage parking lot information.
Expected Behavior:
- When a vehicle successfully parks, it should occupy a spot, and the count of available spots should decrease.
- When a vehicle successfully unparks, it should free up a spot, and the count of available spots should increase.
- Attempting to park a vehicle when no spots are available should result in an error.
- Attempting to unpark a vehicle that is not currently parked should result in an error.
- The system should provide an accurate count of available spots at any given time.
- The system should be able to list all vehicles currently parked.
Edge Cases to Consider:
- Parking lot with zero capacity.
- Unparking a vehicle multiple times.
- Parking a vehicle that is already parked.
- Case sensitivity of vehicle identifiers.
Examples
Example 1: Basic Parking and Unparking
// Initialize a parking lot with capacity 2
let mut parking_lot = ParkingLot::new(2);
// Park vehicle "ABC-123"
let result1 = parking_lot.park("ABC-123");
assert!(result1.is_ok());
assert_eq!(parking_lot.available_spots(), 1);
// Park vehicle "XYZ-789"
let result2 = parking_lot.park("XYZ-789");
assert!(result2.is_ok());
assert_eq!(parking_lot.available_spots(), 0);
// Try to park when full
let result3 = parking_lot.park("DEF-456");
assert!(result3.is_err()); // Should error because lot is full
assert_eq!(parking_lot.available_spots(), 0);
// Unpark vehicle "ABC-123"
let result4 = parking_lot.unpark("ABC-123");
assert!(result4.is_ok());
assert_eq!(parking_lot.available_spots(), 1);
// List occupied spots
let occupied = parking_lot.occupied_vehicles();
assert_eq!(occupied, vec!["XYZ-789"]);
Explanation: The parking lot starts with 2 spots. Two vehicles are successfully parked, filling the lot. The third parking attempt fails. Then, one vehicle unparks, freeing a spot. Finally, the list of occupied vehicles is retrieved.
Example 2: Unparking Non-existent Vehicle
// Initialize a parking lot with capacity 1
let mut parking_lot = ParkingLot::new(1);
// Park vehicle "AAA-111"
parking_lot.park("AAA-111").unwrap();
assert_eq!(parking_lot.available_spots(), 0);
// Try to unpark a vehicle that is not present
let result = parking_lot.unpark("BBB-222");
assert!(result.is_err()); // Should error because vehicle is not parked
assert_eq!(parking_lot.available_spots(), 0);
Explanation: A single spot is occupied. When attempting to unpark a vehicle that was never parked, an error is returned, and the parking lot state remains unchanged.
Example 3: Parking a Vehicle Already Inside
// Initialize a parking lot with capacity 2
let mut parking_lot = ParkingLot::new(2);
// Park vehicle "MY-CAR"
parking_lot.park("MY-CAR").unwrap();
assert_eq!(parking_lot.available_spots(), 1);
// Try to park the same vehicle again
let result = parking_lot.park("MY-CAR");
assert!(result.is_err()); // Should error because vehicle is already parked
assert_eq!(parking_lot.available_spots(), 1);
Explanation: A vehicle is parked. Attempting to park the same vehicle again results in an error, as duplicates are not allowed.
Constraints
- The capacity of the parking lot will be a non-negative integer.
- Vehicle identifiers will be non-empty strings.
- The number of parking operations will not exceed reasonable limits for typical competitive programming scenarios (e.g., up to 10^5 operations).
- Your solution should aim for efficient time complexity for parking and unparking operations.
Notes
- Consider using
std::collections::HashMapfor efficient lookup of parked vehicles. - Define custom error types for clarity when operations fail.
- Think about how to represent the state of each parking spot.
- Case sensitivity of vehicle identifiers is up to your implementation, but be consistent.