瀏覽代碼

Add Parking Lot Solution

Donne Martin 8 年之前
父節點
當前提交
831906f96c

+ 0 - 0
solutions/object_oriented_design/parking_lot/__init__.py


+ 204 - 0
solutions/object_oriented_design/parking_lot/parking_lot.ipynb

@@ -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 - 0
solutions/object_oriented_design/parking_lot/parking_lot.py

@@ -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):  # ...