forked from donnemartin/system-design-primer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
616710f
commit 831906f
Showing
3 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
204 changes: 204 additions & 0 deletions
204
solutions/object_oriented_design/parking_lot/parking_lot.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
121 changes: 121 additions & 0 deletions
121
solutions/object_oriented_design/parking_lot/parking_lot.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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): # ... |