Add Parking Lot Solution
parent
616710f42e
commit
831906f96c
|
@ -0,0 +1,204 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/system-design-primer-primer)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Design a parking lot"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Constraints and assumptions\n",
|
||||||
|
"\n",
|
||||||
|
"* What types of vehicles should we support?\n",
|
||||||
|
" * Motorcycle, Car, Bus\n",
|
||||||
|
"* Does each vehicle type take up a different amount of parking spots?\n",
|
||||||
|
" * Yes\n",
|
||||||
|
" * Motorcycle spot -> Motorcycle\n",
|
||||||
|
" * Compact spot -> Motorcycle, Car\n",
|
||||||
|
" * Large spot -> Motorcycle, Car\n",
|
||||||
|
" * Bus can park if we have 5 consecutive \"large\" spots\n",
|
||||||
|
"* Does the parking lot have multiple levels?\n",
|
||||||
|
" * Yes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Solution"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {
|
||||||
|
"collapsed": false
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Overwriting parking_lot.py\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"%%writefile parking_lot.py\n",
|
||||||
|
"from abc import ABCMeta, abstractmethod\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class VehicleSize(Enum):\n",
|
||||||
|
"\n",
|
||||||
|
" MOTORCYCLE = 0\n",
|
||||||
|
" COMPACT = 1\n",
|
||||||
|
" LARGE = 2\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class Vehicle(metaclass=ABCMeta):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, vehicle_size, license_plate, spot_size):\n",
|
||||||
|
" self.vehicle_size = vehicle_size\n",
|
||||||
|
" self.license_plate = license_plate\n",
|
||||||
|
" self.spot_size\n",
|
||||||
|
" self.spots_taken = []\n",
|
||||||
|
"\n",
|
||||||
|
" def clear_spots(self):\n",
|
||||||
|
" for spot in self.spots_taken:\n",
|
||||||
|
" spot.remove_vehicle(self)\n",
|
||||||
|
" self.spots_taken = []\n",
|
||||||
|
"\n",
|
||||||
|
" def take_spot(self, spot):\n",
|
||||||
|
" self.spots_taken.append(spot)\n",
|
||||||
|
"\n",
|
||||||
|
" @abstractmethod\n",
|
||||||
|
" def can_fit_in_spot(self, spot):\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class Motorcycle(Vehicle):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, license_plate):\n",
|
||||||
|
" super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1)\n",
|
||||||
|
"\n",
|
||||||
|
" def can_fit_in_spot(self, spot):\n",
|
||||||
|
" return True\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class Car(Vehicle):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, license_plate):\n",
|
||||||
|
" super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1)\n",
|
||||||
|
"\n",
|
||||||
|
" def can_fit_in_spot(self, spot):\n",
|
||||||
|
" return True if (spot.size == LARGE or spot.size == COMPACT) else False\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class Bus(Vehicle):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, license_plate):\n",
|
||||||
|
" super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5)\n",
|
||||||
|
"\n",
|
||||||
|
" def can_fit_in_spot(self, spot):\n",
|
||||||
|
" return True if spot.size == LARGE else False\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class ParkingLot(object):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, num_levels):\n",
|
||||||
|
" self.num_levels = num_levels\n",
|
||||||
|
" self.levels = []\n",
|
||||||
|
"\n",
|
||||||
|
" def park_vehicle(self, vehicle):\n",
|
||||||
|
" for level in levels:\n",
|
||||||
|
" if level.park_vehicle(vehicle):\n",
|
||||||
|
" return True\n",
|
||||||
|
" return False\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class Level(object):\n",
|
||||||
|
"\n",
|
||||||
|
" SPOTS_PER_ROW = 10\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, floor, total_spots):\n",
|
||||||
|
" self.floor = floor\n",
|
||||||
|
" self.num_spots = total_spots\n",
|
||||||
|
" self.available_spots = 0\n",
|
||||||
|
" self.parking_spots = []\n",
|
||||||
|
"\n",
|
||||||
|
" def spot_freed(self):\n",
|
||||||
|
" self.available_spots += 1\n",
|
||||||
|
"\n",
|
||||||
|
" def park_vehicle(self, vehicle):\n",
|
||||||
|
" spot = self._find_available_spot(vehicle)\n",
|
||||||
|
" if spot is None:\n",
|
||||||
|
" return None\n",
|
||||||
|
" else:\n",
|
||||||
|
" spot.park_vehicle(vehicle)\n",
|
||||||
|
" return spot\n",
|
||||||
|
"\n",
|
||||||
|
" def _find_available_spot(self, vehicle):\n",
|
||||||
|
" \"\"\"Find an available spot where vehicle can fit, or return None\"\"\"\n",
|
||||||
|
" # ...\n",
|
||||||
|
"\n",
|
||||||
|
" def _park_starting_at_spot(self, spot, vehicle):\n",
|
||||||
|
" \"\"\"Occupy starting at spot.spot_number to vehicle.spot_size.\"\"\"\n",
|
||||||
|
" # ...\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class ParkingSpot(object):\n",
|
||||||
|
"\n",
|
||||||
|
" def __init__(self, level, row, spot_number, spot_size, vehicle_size):\n",
|
||||||
|
" self.level = level\n",
|
||||||
|
" self.row = row\n",
|
||||||
|
" self.spot_number = spot_number\n",
|
||||||
|
" self.spot_size = spot_size\n",
|
||||||
|
" self.vehicle_size = vehicle_size\n",
|
||||||
|
" self.vehicle = None\n",
|
||||||
|
"\n",
|
||||||
|
" def is_available(self):\n",
|
||||||
|
" return True if self.vehicle is None else False\n",
|
||||||
|
"\n",
|
||||||
|
" def can_fit_vehicle(self, vehicle):\n",
|
||||||
|
" if self.vehicle is not None:\n",
|
||||||
|
" return False\n",
|
||||||
|
" return vehicle.can_fit_in_spot(self)\n",
|
||||||
|
"\n",
|
||||||
|
" def park_vehicle(self, vehicle): # ...\n",
|
||||||
|
" def remove_vehicle(self): # ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.4.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 0
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class VehicleSize(Enum):
|
||||||
|
|
||||||
|
MOTORCYCLE = 0
|
||||||
|
COMPACT = 1
|
||||||
|
LARGE = 2
|
||||||
|
|
||||||
|
|
||||||
|
class Vehicle(metaclass=ABCMeta):
|
||||||
|
|
||||||
|
def __init__(self, vehicle_size, license_plate, spot_size):
|
||||||
|
self.vehicle_size = vehicle_size
|
||||||
|
self.license_plate = license_plate
|
||||||
|
self.spot_size
|
||||||
|
self.spots_taken = []
|
||||||
|
|
||||||
|
def clear_spots(self):
|
||||||
|
for spot in self.spots_taken:
|
||||||
|
spot.remove_vehicle(self)
|
||||||
|
self.spots_taken = []
|
||||||
|
|
||||||
|
def take_spot(self, spot):
|
||||||
|
self.spots_taken.append(spot)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def can_fit_in_spot(self, spot):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Motorcycle(Vehicle):
|
||||||
|
|
||||||
|
def __init__(self, license_plate):
|
||||||
|
super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1)
|
||||||
|
|
||||||
|
def can_fit_in_spot(self, spot):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class Car(Vehicle):
|
||||||
|
|
||||||
|
def __init__(self, license_plate):
|
||||||
|
super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1)
|
||||||
|
|
||||||
|
def can_fit_in_spot(self, spot):
|
||||||
|
return True if (spot.size == LARGE or spot.size == COMPACT) else False
|
||||||
|
|
||||||
|
|
||||||
|
class Bus(Vehicle):
|
||||||
|
|
||||||
|
def __init__(self, license_plate):
|
||||||
|
super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5)
|
||||||
|
|
||||||
|
def can_fit_in_spot(self, spot):
|
||||||
|
return True if spot.size == LARGE else False
|
||||||
|
|
||||||
|
|
||||||
|
class ParkingLot(object):
|
||||||
|
|
||||||
|
def __init__(self, num_levels):
|
||||||
|
self.num_levels = num_levels
|
||||||
|
self.levels = [] # List of Levels
|
||||||
|
|
||||||
|
def park_vehicle(self, vehicle):
|
||||||
|
for level in levels:
|
||||||
|
if level.park_vehicle(vehicle):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Level(object):
|
||||||
|
|
||||||
|
SPOTS_PER_ROW = 10
|
||||||
|
|
||||||
|
def __init__(self, floor, total_spots):
|
||||||
|
self.floor = floor
|
||||||
|
self.num_spots = total_spots
|
||||||
|
self.available_spots = 0
|
||||||
|
self.spots = [] # List of ParkingSpots
|
||||||
|
|
||||||
|
def spot_freed(self):
|
||||||
|
self.available_spots += 1
|
||||||
|
|
||||||
|
def park_vehicle(self, vehicle):
|
||||||
|
spot = self._find_available_spot(vehicle)
|
||||||
|
if spot is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
spot.park_vehicle(vehicle)
|
||||||
|
return spot
|
||||||
|
|
||||||
|
def _find_available_spot(self, vehicle):
|
||||||
|
"""Find an available spot where vehicle can fit, or return None"""
|
||||||
|
# ...
|
||||||
|
|
||||||
|
def _park_starting_at_spot(self, spot, vehicle):
|
||||||
|
"""Occupy starting at spot.spot_number to vehicle.spot_size."""
|
||||||
|
# ...
|
||||||
|
|
||||||
|
|
||||||
|
class ParkingSpot(object):
|
||||||
|
|
||||||
|
def __init__(self, level, row, spot_number, spot_size, vehicle_size):
|
||||||
|
self.level = level
|
||||||
|
self.row = row
|
||||||
|
self.spot_number = spot_number
|
||||||
|
self.spot_size = spot_size
|
||||||
|
self.vehicle_size = vehicle_size
|
||||||
|
self.vehicle = None
|
||||||
|
|
||||||
|
def is_available(self):
|
||||||
|
return True if self.vehicle is None else False
|
||||||
|
|
||||||
|
def can_fit_vehicle(self, vehicle):
|
||||||
|
if self.vehicle is not None:
|
||||||
|
return False
|
||||||
|
return vehicle.can_fit_in_spot(self)
|
||||||
|
|
||||||
|
def park_vehicle(self, vehicle): # ...
|
||||||
|
def remove_vehicle(self): # ...
|
Loading…
Reference in New Issue