Commit 1f939ec3 authored by Narendra Choudhary Legha's avatar Narendra Choudhary Legha Committed by Donne Martin
Browse files

Resolve #195: Fix broken GitHub URLs (#199)

parent ffbcd9a3
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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)." "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)."
] ]
}, },
{ {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
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). 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).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design a deck of cards # Design a deck of cards
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* Is this a generic deck of cards for games like poker and black jack? * Is this a generic deck of cards for games like poker and black jack?
* Yes, design a generic deck then extend it to black jack * Yes, design a generic deck then extend it to black jack
* Can we assume the deck has 52 cards (2-10, Jack, Queen, King, Ace) and 4 suits? * Can we assume the deck has 52 cards (2-10, Jack, Queen, King, Ace) and 4 suits?
* Yes * Yes
* Can we assume inputs are valid or do we have to validate them? * Can we assume inputs are valid or do we have to validate them?
* Assume they're valid * Assume they're valid
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile deck_of_cards.py %%writefile deck_of_cards.py
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from enum import Enum from enum import Enum
import sys import sys
class Suit(Enum): class Suit(Enum):
HEART = 0 HEART = 0
DIAMOND = 1 DIAMOND = 1
CLUBS = 2 CLUBS = 2
SPADE = 3 SPADE = 3
class Card(metaclass=ABCMeta): class Card(metaclass=ABCMeta):
def __init__(self, value, suit): def __init__(self, value, suit):
self.value = value self.value = value
self.suit = suit self.suit = suit
self.is_available = True self.is_available = True
@property @property
@abstractmethod @abstractmethod
def value(self): def value(self):
pass pass
@value.setter @value.setter
@abstractmethod @abstractmethod
def value(self, other): def value(self, other):
pass pass
class BlackJackCard(Card): class BlackJackCard(Card):
def __init__(self, value, suit): def __init__(self, value, suit):
super(BlackJackCard, self).__init__(value, suit) super(BlackJackCard, self).__init__(value, suit)
def is_ace(self): def is_ace(self):
return self._value == 1 return self._value == 1
def is_face_card(self): def is_face_card(self):
"""Jack = 11, Queen = 12, King = 13""" """Jack = 11, Queen = 12, King = 13"""
return 10 < self._value <= 13 return 10 < self._value <= 13
@property @property
def value(self): def value(self):
if self.is_ace() == 1: if self.is_ace() == 1:
return 1 return 1
elif self.is_face_card(): elif self.is_face_card():
return 10 return 10
else: else:
return self._value return self._value
@value.setter @value.setter
def value(self, new_value): def value(self, new_value):
if 1 <= new_value <= 13: if 1 <= new_value <= 13:
self._value = new_value self._value = new_value
else: else:
raise ValueError('Invalid card value: {}'.format(new_value)) raise ValueError('Invalid card value: {}'.format(new_value))
class Hand(object): class Hand(object):
def __init__(self, cards): def __init__(self, cards):
self.cards = cards self.cards = cards
def add_card(self, card): def add_card(self, card):
self.cards.append(card) self.cards.append(card)
def score(self): def score(self):
total_value = 0 total_value = 0
for card in card: for card in card:
total_value += card.value total_value += card.value
return total_value return total_value
class BlackJackHand(Hand): class BlackJackHand(Hand):
BLACKJACK = 21 BLACKJACK = 21
def __init__(self, cards): def __init__(self, cards):
super(BlackJackHand, self).__init__(cards) super(BlackJackHand, self).__init__(cards)
def score(self): def score(self):
min_over = sys.MAXSIZE min_over = sys.MAXSIZE
max_under = -sys.MAXSIZE max_under = -sys.MAXSIZE
for score in self.possible_scores(): for score in self.possible_scores():
if self.BLACKJACK < score < min_over: if self.BLACKJACK < score < min_over:
min_over = score min_over = score
elif max_under < score <= self.BLACKJACK: elif max_under < score <= self.BLACKJACK:
max_under = score max_under = score
return max_under if max_under != -sys.MAXSIZE else min_over return max_under if max_under != -sys.MAXSIZE else min_over
def possible_scores(self): def possible_scores(self):
"""Return a list of possible scores, taking Aces into account.""" """Return a list of possible scores, taking Aces into account."""
# ... # ...
class Deck(object): class Deck(object):
def __init__(self, cards): def __init__(self, cards):
self.cards = cards self.cards = cards
self.deal_index = 0 self.deal_index = 0
def remaining_cards(self): def remaining_cards(self):
return len(self.cards) - deal_index return len(self.cards) - deal_index
def deal_card(): def deal_card():
try: try:
card = self.cards[self.deal_index] card = self.cards[self.deal_index]
card.is_available = False card.is_available = False
self.deal_index += 1 self.deal_index += 1
except IndexError: except IndexError:
return None return None
return card return card
def shuffle(self): # ... def shuffle(self): # ...
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting deck_of_cards.py Overwriting deck_of_cards.py
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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)." "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)."
] ]
}, },
{ {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
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). 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).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design a hash map # Design a hash map
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* For simplicity, are the keys integers only? * For simplicity, are the keys integers only?
* Yes * Yes
* For collision resolution, can we use chaining? * For collision resolution, can we use chaining?
* Yes * Yes
* Do we have to worry about load factors? * Do we have to worry about load factors?
* No * No
* Can we assume inputs are valid or do we have to validate them? * Can we assume inputs are valid or do we have to validate them?
* Assume they're valid * Assume they're valid
* Can we assume this fits memory? * Can we assume this fits memory?
* Yes * Yes
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile hash_map.py %%writefile hash_map.py
class Item(object): class Item(object):
def __init__(self, key, value): def __init__(self, key, value):
self.key = key self.key = key
self.value = value self.value = value
class HashTable(object): class HashTable(object):
def __init__(self, size): def __init__(self, size):
self.size = size self.size = size
self.table = [[] for _ in range(self.size)] self.table = [[] for _ in range(self.size)]
def _hash_function(self, key): def _hash_function(self, key):
return key % self.size return key % self.size
def set(self, key, value): def set(self, key, value):
hash_index = self._hash_function(key) hash_index = self._hash_function(key)
for item in self.table[hash_index]: for item in self.table[hash_index]:
if item.key == key: if item.key == key:
item.value = value item.value = value
return return
self.table[hash_index].append(Item(key, value)) self.table[hash_index].append(Item(key, value))
def get(self, key): def get(self, key):
hash_index = self._hash_function(key) hash_index = self._hash_function(key)
for item in self.table[hash_index]: for item in self.table[hash_index]:
if item.key == key: if item.key == key:
return item.value return item.value
raise KeyError('Key not found') raise KeyError('Key not found')
def remove(self, key): def remove(self, key):
hash_index = self._hash_function(key) hash_index = self._hash_function(key)
for index, item in enumerate(self.table[hash_index]): for index, item in enumerate(self.table[hash_index]):
if item.key == key: if item.key == key:
del self.table[hash_index][index] del self.table[hash_index][index]
return return
raise KeyError('Key not found') raise KeyError('Key not found')
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting hash_map.py Overwriting hash_map.py
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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)." "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)."
] ]
}, },
{ {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
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). 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).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design an LRU cache # Design an LRU cache
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* What are we caching? * What are we caching?
* We are caching the results of web queries * We are caching the results of web queries
* Can we assume inputs are valid or do we have to validate them? * Can we assume inputs are valid or do we have to validate them?
* Assume they're valid * Assume they're valid
* Can we assume this fits memory? * Can we assume this fits memory?
* Yes * Yes
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile lru_cache.py %%writefile lru_cache.py
class Node(object): class Node(object):
def __init__(self, results): def __init__(self, results):
self.results = results self.results = results
self.prev = None self.prev = None
self.next = None self.next = None
class LinkedList(object): class LinkedList(object):
def __init__(self): def __init__(self):
self.head = None self.head = None
self.tail = None self.tail = None
def move_to_front(self, node): # ... def move_to_front(self, node): # ...
def append_to_front(self, node): # ... def append_to_front(self, node): # ...
def remove_from_tail(self): # ... def remove_from_tail(self): # ...
class Cache(object): class Cache(object):
def __init__(self, MAX_SIZE): def __init__(self, MAX_SIZE):
self.MAX_SIZE = MAX_SIZE self.MAX_SIZE = MAX_SIZE
self.size = 0 self.size = 0
self.lookup = {} # key: query, value: node self.lookup = {} # key: query, value: node
self.linked_list = LinkedList() self.linked_list = LinkedList()
def get(self, query) def get(self, query)
"""Get the stored query result from the cache. """Get the stored query result from the cache.
Accessing a node updates its position to the front of the LRU list. Accessing a node updates its position to the front of the LRU list.
""" """
node = self.lookup.get(query) node = self.lookup.get(query)
if node is None: if node is None:
return None return None
self.linked_list.move_to_front(node) self.linked_list.move_to_front(node)
return node.results return node.results
def set(self, results, query): def set(self, results, query):
"""Set the result for the given query key in the cache. """Set the result for the given query key in the cache.
When updating an entry, updates its position to the front of the LRU list. When updating an entry, updates its position to the front of the LRU list.
If the entry is new and the cache is at capacity, removes the oldest entry If the entry is new and the cache is at capacity, removes the oldest entry
before the new entry is added. before the new entry is added.
""" """
node = self.lookup.get(query) node = self.lookup.get(query)
if node is not None: if node is not None:
# Key exists in cache, update the value # Key exists in cache, update the value
node.results = results node.results = results
self.linked_list.move_to_front(node) self.linked_list.move_to_front(node)
else: else:
# Key does not exist in cache # Key does not exist in cache
if self.size == self.MAX_SIZE: if self.size == self.MAX_SIZE:
# Remove the oldest entry from the linked list and lookup # Remove the oldest entry from the linked list and lookup
self.lookup.pop(self.linked_list.tail.query, None) self.lookup.pop(self.linked_list.tail.query, None)
self.linked_list.remove_from_tail() self.linked_list.remove_from_tail()
else: else:
self.size += 1 self.size += 1
# Add the new key and value # Add the new key and value
new_node = Node(results) new_node = Node(results)
self.linked_list.append_to_front(new_node) self.linked_list.append_to_front(new_node)
self.lookup[query] = new_node self.lookup[query] = new_node
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting lru_cache.py Overwriting lru_cache.py
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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)." "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)."
] ]
}, },
{ {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
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). 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).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design an online chat # Design an online chat
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* Assume we'll focus on the following workflows: * Assume we'll focus on the following workflows:
* Text conversations only * Text conversations only
* Users * Users
* Add a user * Add a user
* Remove a user * Remove a user
* Update a user * Update a user
* Add to a user's friends list * Add to a user's friends list
* Add friend request * Add friend request
* Approve friend request * Approve friend request
* Reject friend request * Reject friend request
* Remove from a user's friends list * Remove from a user's friends list
* Create a group chat * Create a group chat
* Invite friends to a group chat * Invite friends to a group chat
* Post a message to a group chat * Post a message to a group chat
* Private 1-1 chat * Private 1-1 chat
* Invite a friend to a private chat * Invite a friend to a private chat
* Post a meesage to a private chat * Post a meesage to a private chat
* No need to worry about scaling initially * No need to worry about scaling initially
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile online_chat.py %%writefile online_chat.py
from abc import ABCMeta from abc import ABCMeta
class UserService(object): class UserService(object):
def __init__(self): def __init__(self):
self.users_by_id = {} # key: user id, value: User self.users_by_id = {} # key: user id, value: User
def add_user(self, user_id, name, pass_hash): # ... def add_user(self, user_id, name, pass_hash): # ...
def remove_user(self, user_id): # ... def remove_user(self, user_id): # ...
def add_friend_request(self, from_user_id, to_user_id): # ... def add_friend_request(self, from_user_id, to_user_id): # ...
def approve_friend_request(self, from_user_id, to_user_id): # ... def approve_friend_request(self, from_user_id, to_user_id): # ...
def reject_friend_request(self, from_user_id, to_user_id): # ... def reject_friend_request(self, from_user_id, to_user_id): # ...
class User(object): class User(object):
def __init__(self, user_id, name, pass_hash): def __init__(self, user_id, name, pass_hash):
self.user_id = user_id self.user_id = user_id
self.name = name self.name = name
self.pass_hash = pass_hash self.pass_hash = pass_hash
self.friends_by_id = {} # key: friend id, value: User self.friends_by_id = {} # key: friend id, value: User
self.friend_ids_to_private_chats = {} # key: friend id, value: private chats self.friend_ids_to_private_chats = {} # key: friend id, value: private chats
self.group_chats_by_id = {} # key: chat id, value: GroupChat self.group_chats_by_id = {} # key: chat id, value: GroupChat
self.received_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest self.received_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest
self.sent_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest self.sent_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest
def message_user(self, friend_id, message): # ... def message_user(self, friend_id, message): # ...
def message_group(self, group_id, message): # ... def message_group(self, group_id, message): # ...
def send_friend_request(self, friend_id): # ... def send_friend_request(self, friend_id): # ...
def receive_friend_request(self, friend_id): # ... def receive_friend_request(self, friend_id): # ...
def approve_friend_request(self, friend_id): # ... def approve_friend_request(self, friend_id): # ...
def reject_friend_request(self, friend_id): # ... def reject_friend_request(self, friend_id): # ...
class Chat(metaclass=ABCMeta): class Chat(metaclass=ABCMeta):
def __init__(self, chat_id): def __init__(self, chat_id):
self.chat_id = chat_id self.chat_id = chat_id
self.users = [] self.users = []
self.messages = [] self.messages = []
class PrivateChat(Chat): class PrivateChat(Chat):
def __init__(self, first_user, second_user): def __init__(self, first_user, second_user):
super(PrivateChat, self).__init__() super(PrivateChat, self).__init__()
self.users.append(first_user) self.users.append(first_user)
self.users.append(second_user) self.users.append(second_user)
class GroupChat(Chat): class GroupChat(Chat):
def add_user(self, user): # ... def add_user(self, user): # ...
def remove_user(self, user): # ... def remove_user(self, user): # ...
class Message(object): class Message(object):
def __init__(self, message_id, message, timestamp): def __init__(self, message_id, message, timestamp):
self.message_id = message_id self.message_id = message_id
self.message = message self.message = message
self.timestamp = timestamp self.timestamp = timestamp
class AddRequest(object): class AddRequest(object):
def __init__(self, from_user_id, to_user_id, request_status, timestamp): def __init__(self, from_user_id, to_user_id, request_status, timestamp):
self.from_user_id = from_user_id self.from_user_id = from_user_id
self.to_user_id = to_user_id self.to_user_id = to_user_id
self.request_status = request_status self.request_status = request_status
self.timestamp = timestamp self.timestamp = timestamp
class RequestStatus(Enum): class RequestStatus(Enum):
UNREAD = 0 UNREAD = 0
READ = 1 READ = 1
ACCEPTED = 2 ACCEPTED = 2
REJECTED = 3 REJECTED = 3
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting online_chat.py Overwriting online_chat.py
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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)." "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)."
] ]
}, },
{ {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
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). 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).
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Design a parking lot # Design a parking lot
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Constraints and assumptions ## Constraints and assumptions
* What types of vehicles should we support? * What types of vehicles should we support?
* Motorcycle, Car, Bus * Motorcycle, Car, Bus
* Does each vehicle type take up a different amount of parking spots? * Does each vehicle type take up a different amount of parking spots?
* Yes * Yes
* Motorcycle spot -> Motorcycle * Motorcycle spot -> Motorcycle
* Compact spot -> Motorcycle, Car * Compact spot -> Motorcycle, Car
* Large spot -> Motorcycle, Car * Large spot -> Motorcycle, Car
* Bus can park if we have 5 consecutive "large" spots * Bus can park if we have 5 consecutive "large" spots
* Does the parking lot have multiple levels? * Does the parking lot have multiple levels?
* Yes * Yes
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Solution ## Solution
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%%writefile parking_lot.py %%writefile parking_lot.py
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
class VehicleSize(Enum): class VehicleSize(Enum):
MOTORCYCLE = 0 MOTORCYCLE = 0
COMPACT = 1 COMPACT = 1
LARGE = 2 LARGE = 2
class Vehicle(metaclass=ABCMeta): class Vehicle(metaclass=ABCMeta):
def __init__(self, vehicle_size, license_plate, spot_size): def __init__(self, vehicle_size, license_plate, spot_size):
self.vehicle_size = vehicle_size self.vehicle_size = vehicle_size
self.license_plate = license_plate self.license_plate = license_plate
self.spot_size = spot_size self.spot_size = spot_size
self.spots_taken = [] self.spots_taken = []
def clear_spots(self): def clear_spots(self):
for spot in self.spots_taken: for spot in self.spots_taken:
spot.remove_vehicle(self) spot.remove_vehicle(self)
self.spots_taken = [] self.spots_taken = []
def take_spot(self, spot): def take_spot(self, spot):
self.spots_taken.append(spot) self.spots_taken.append(spot)
@abstractmethod @abstractmethod
def can_fit_in_spot(self, spot): def can_fit_in_spot(self, spot):
pass pass
class Motorcycle(Vehicle): class Motorcycle(Vehicle):
def __init__(self, license_plate): def __init__(self, license_plate):
super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1) super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1)
def can_fit_in_spot(self, spot): def can_fit_in_spot(self, spot):
return True return True
class Car(Vehicle): class Car(Vehicle):
def __init__(self, license_plate): def __init__(self, license_plate):
super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1) super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1)
def can_fit_in_spot(self, spot): def can_fit_in_spot(self, spot):
return True if (spot.size == LARGE or spot.size == COMPACT) else False return True if (spot.size == LARGE or spot.size == COMPACT) else False
class Bus(Vehicle): class Bus(Vehicle):
def __init__(self, license_plate): def __init__(self, license_plate):
super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5) super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5)
def can_fit_in_spot(self, spot): def can_fit_in_spot(self, spot):
return True if spot.size == LARGE else False return True if spot.size == LARGE else False
class ParkingLot(object): class ParkingLot(object):
def __init__(self, num_levels): def __init__(self, num_levels):
self.num_levels = num_levels self.num_levels = num_levels
self.levels = [] self.levels = []
def park_vehicle(self, vehicle): def park_vehicle(self, vehicle):
for level in levels: for level in levels:
if level.park_vehicle(vehicle): if level.park_vehicle(vehicle):
return True return True
return False return False
class Level(object): class Level(object):
SPOTS_PER_ROW = 10 SPOTS_PER_ROW = 10
def __init__(self, floor, total_spots): def __init__(self, floor, total_spots):
self.floor = floor self.floor = floor
self.num_spots = total_spots self.num_spots = total_spots
self.available_spots = 0 self.available_spots = 0
self.parking_spots = [] self.parking_spots = []
def spot_freed(self): def spot_freed(self):
self.available_spots += 1 self.available_spots += 1
def park_vehicle(self, vehicle): def park_vehicle(self, vehicle):
spot = self._find_available_spot(vehicle) spot = self._find_available_spot(vehicle)
if spot is None: if spot is None:
return None return None
else: else:
spot.park_vehicle(vehicle) spot.park_vehicle(vehicle)
return spot return spot
def _find_available_spot(self, vehicle): def _find_available_spot(self, vehicle):
"""Find an available spot where vehicle can fit, or return None""" """Find an available spot where vehicle can fit, or return None"""
# ... # ...
def _park_starting_at_spot(self, spot, vehicle): def _park_starting_at_spot(self, spot, vehicle):
"""Occupy starting at spot.spot_number to vehicle.spot_size.""" """Occupy starting at spot.spot_number to vehicle.spot_size."""
# ... # ...
class ParkingSpot(object): class ParkingSpot(object):
def __init__(self, level, row, spot_number, spot_size, vehicle_size): def __init__(self, level, row, spot_number, spot_size, vehicle_size):
self.level = level self.level = level
self.row = row self.row = row
self.spot_number = spot_number self.spot_number = spot_number
self.spot_size = spot_size self.spot_size = spot_size
self.vehicle_size = vehicle_size self.vehicle_size = vehicle_size
self.vehicle = None self.vehicle = None
def is_available(self): def is_available(self):
return True if self.vehicle is None else False return True if self.vehicle is None else False
def can_fit_vehicle(self, vehicle): def can_fit_vehicle(self, vehicle):
if self.vehicle is not None: if self.vehicle is not None:
return False return False
return vehicle.can_fit_in_spot(self) return vehicle.can_fit_in_spot(self)
def park_vehicle(self, vehicle): # ... def park_vehicle(self, vehicle): # ...
def remove_vehicle(self): # ... def remove_vehicle(self): # ...
``` ```
%%%% Output: stream %%%% Output: stream
Overwriting parking_lot.py Overwriting parking_lot.py
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment