|
@@ -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
|
|
|
+}
|