poriting to noat.cards

This commit is contained in:
Vu
2021-03-14 17:08:05 +07:00
parent 6984b4e956
commit f4af06bdff
48 changed files with 3545 additions and 3384 deletions

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -67,118 +67,118 @@
"from enum import Enum\n",
"\n",
"\n",
"class Rank(Enum):\n",
"class Rank(Enum) :\n",
"\n",
" OPERATOR = 0\n",
" SUPERVISOR = 1\n",
" DIRECTOR = 2\n",
"\n",
"\n",
"class Employee(metaclass=ABCMeta):\n",
"class Employee(metaclass=ABCMeta) :\n",
"\n",
" def __init__(self, employee_id, name, rank, call_center):\n",
" def __init__(self, employee_id, name, rank, call_center) :\n",
" self.employee_id = employee_id\n",
" self.name = name\n",
" self.rank = rank\n",
" self.call = None\n",
" self.call_center = call_center\n",
"\n",
" def take_call(self, call):\n",
" def take_call(self, call) :\n",
" \"\"\"Assume the employee will always successfully take the call.\"\"\"\n",
" self.call = call\n",
" self.call.employee = self\n",
" self.call.state = CallState.IN_PROGRESS\n",
"\n",
" def complete_call(self):\n",
" def complete_call(self) :\n",
" self.call.state = CallState.COMPLETE\n",
" self.call_center.notify_call_completed(self.call)\n",
" self.call_center.notify_call_completed(self.call) \n",
"\n",
" @abstractmethod\n",
" def escalate_call(self):\n",
" def escalate_call(self) :\n",
" pass\n",
"\n",
" def _escalate_call(self):\n",
" def _escalate_call(self) :\n",
" self.call.state = CallState.READY\n",
" call = self.call\n",
" self.call = None\n",
" self.call_center.notify_call_escalated(call)\n",
" self.call_center.notify_call_escalated(call) \n",
"\n",
"\n",
"class Operator(Employee):\n",
"class Operator(Employee) :\n",
"\n",
" def __init__(self, employee_id, name):\n",
" super(Operator, self).__init__(employee_id, name, Rank.OPERATOR)\n",
" def __init__(self, employee_id, name) :\n",
" super(Operator, self) .__init__(employee_id, name, Rank.OPERATOR) \n",
"\n",
" def escalate_call(self):\n",
" def escalate_call(self) :\n",
" self.call.level = Rank.SUPERVISOR\n",
" self._escalate_call()\n",
" self._escalate_call() \n",
"\n",
"\n",
"class Supervisor(Employee):\n",
"class Supervisor(Employee) :\n",
"\n",
" def __init__(self, employee_id, name):\n",
" super(Operator, self).__init__(employee_id, name, Rank.SUPERVISOR)\n",
" def __init__(self, employee_id, name) :\n",
" super(Operator, self) .__init__(employee_id, name, Rank.SUPERVISOR) \n",
"\n",
" def escalate_call(self):\n",
" def escalate_call(self) :\n",
" self.call.level = Rank.DIRECTOR\n",
" self._escalate_call()\n",
" self._escalate_call() \n",
"\n",
"\n",
"class Director(Employee):\n",
"class Director(Employee) :\n",
"\n",
" def __init__(self, employee_id, name):\n",
" super(Operator, self).__init__(employee_id, name, Rank.DIRECTOR)\n",
" def __init__(self, employee_id, name) :\n",
" super(Operator, self) .__init__(employee_id, name, Rank.DIRECTOR) \n",
"\n",
" def escalate_call(self):\n",
" raise NotImplemented('Directors must be able to handle any call')\n",
" def escalate_call(self) :\n",
" raise NotImplemented('Directors must be able to handle any call') \n",
"\n",
"\n",
"class CallState(Enum):\n",
"class CallState(Enum) :\n",
"\n",
" READY = 0\n",
" IN_PROGRESS = 1\n",
" COMPLETE = 2\n",
"\n",
"\n",
"class Call(object):\n",
"class Call(object) :\n",
"\n",
" def __init__(self, rank):\n",
" def __init__(self, rank) :\n",
" self.state = CallState.READY\n",
" self.rank = rank\n",
" self.employee = None\n",
"\n",
"\n",
"class CallCenter(object):\n",
"class CallCenter(object) :\n",
"\n",
" def __init__(self, operators, supervisors, directors):\n",
" def __init__(self, operators, supervisors, directors) :\n",
" self.operators = operators\n",
" self.supervisors = supervisors\n",
" self.directors = directors\n",
" self.queued_calls = deque()\n",
" self.queued_calls = deque() \n",
"\n",
" def dispatch_call(self, call):\n",
" if call.rank not in (Rank.OPERATOR, Rank.SUPERVISOR, Rank.DIRECTOR):\n",
" def dispatch_call(self, call) :\n",
" if call.rank not in (Rank.OPERATOR, Rank.SUPERVISOR, Rank.DIRECTOR) :\n",
" raise ValueError('Invalid call rank: {}'.format(call.rank))\n",
" employee = None\n",
" if call.rank == Rank.OPERATOR:\n",
" employee = self._dispatch_call(call, self.operators)\n",
" employee = self._dispatch_call(call, self.operators) \n",
" if call.rank == Rank.SUPERVISOR or employee is None:\n",
" employee = self._dispatch_call(call, self.supervisors)\n",
" employee = self._dispatch_call(call, self.supervisors) \n",
" if call.rank == Rank.DIRECTOR or employee is None:\n",
" employee = self._dispatch_call(call, self.directors)\n",
" employee = self._dispatch_call(call, self.directors) \n",
" if employee is None:\n",
" self.queued_calls.append(call)\n",
" self.queued_calls.append(call) \n",
"\n",
" def _dispatch_call(self, call, employees):\n",
" def _dispatch_call(self, call, employees) :\n",
" for employee in employees:\n",
" if employee.call is None:\n",
" employee.take_call(call)\n",
" employee.take_call(call) \n",
" return employee\n",
" return None\n",
"\n",
" def notify_call_escalated(self, call): # ...\n",
" def notify_call_completed(self, call): # ...\n",
" def dispatch_queued_call_to_newly_freed_employee(self, call, employee): # ..."
" def notify_call_escalated(self, call) : # ...\n",
" def notify_call_completed(self, call) : # ...\n",
" def dispatch_queued_call_to_newly_freed_employee(self, call, employee) : # ..."
]
}
],

View File

@@ -3,120 +3,120 @@ from collections import deque
from enum import Enum
class Rank(Enum):
class Rank(Enum) :
OPERATOR = 0
SUPERVISOR = 1
DIRECTOR = 2
class Employee(metaclass=ABCMeta):
class Employee(metaclass=ABCMeta) :
def __init__(self, employee_id, name, rank, call_center):
def __init__(self, employee_id, name, rank, call_center) :
self.employee_id = employee_id
self.name = name
self.rank = rank
self.call = None
self.call_center = call_center
def take_call(self, call):
def take_call(self, call) :
"""Assume the employee will always successfully take the call."""
self.call = call
self.call.employee = self
self.call.state = CallState.IN_PROGRESS
def complete_call(self):
def complete_call(self) :
self.call.state = CallState.COMPLETE
self.call_center.notify_call_completed(self.call)
self.call_center.notify_call_completed(self.call)
@abstractmethod
def escalate_call(self):
def escalate_call(self) :
pass
def _escalate_call(self):
def _escalate_call(self) :
self.call.state = CallState.READY
call = self.call
self.call = None
self.call_center.notify_call_escalated(call)
self.call_center.notify_call_escalated(call)
class Operator(Employee):
class Operator(Employee) :
def __init__(self, employee_id, name):
super(Operator, self).__init__(employee_id, name, Rank.OPERATOR)
def __init__(self, employee_id, name) :
super(Operator, self) .__init__(employee_id, name, Rank.OPERATOR)
def escalate_call(self):
def escalate_call(self) :
self.call.level = Rank.SUPERVISOR
self._escalate_call()
self._escalate_call()
class Supervisor(Employee):
class Supervisor(Employee) :
def __init__(self, employee_id, name):
super(Operator, self).__init__(employee_id, name, Rank.SUPERVISOR)
def __init__(self, employee_id, name) :
super(Operator, self) .__init__(employee_id, name, Rank.SUPERVISOR)
def escalate_call(self):
def escalate_call(self) :
self.call.level = Rank.DIRECTOR
self._escalate_call()
self._escalate_call()
class Director(Employee):
class Director(Employee) :
def __init__(self, employee_id, name):
super(Operator, self).__init__(employee_id, name, Rank.DIRECTOR)
def __init__(self, employee_id, name) :
super(Operator, self) .__init__(employee_id, name, Rank.DIRECTOR)
def escalate_call(self):
raise NotImplementedError('Directors must be able to handle any call')
def escalate_call(self) :
raise NotImplementedError('Directors must be able to handle any call')
class CallState(Enum):
class CallState(Enum) :
READY = 0
IN_PROGRESS = 1
COMPLETE = 2
class Call(object):
class Call(object) :
def __init__(self, rank):
def __init__(self, rank) :
self.state = CallState.READY
self.rank = rank
self.employee = None
class CallCenter(object):
class CallCenter(object) :
def __init__(self, operators, supervisors, directors):
def __init__(self, operators, supervisors, directors) :
self.operators = operators
self.supervisors = supervisors
self.directors = directors
self.queued_calls = deque()
self.queued_calls = deque()
def dispatch_call(self, call):
if call.rank not in (Rank.OPERATOR, Rank.SUPERVISOR, Rank.DIRECTOR):
def dispatch_call(self, call) :
if call.rank not in (Rank.OPERATOR, Rank.SUPERVISOR, Rank.DIRECTOR) :
raise ValueError('Invalid call rank: {}'.format(call.rank))
employee = None
if call.rank == Rank.OPERATOR:
employee = self._dispatch_call(call, self.operators)
employee = self._dispatch_call(call, self.operators)
if call.rank == Rank.SUPERVISOR or employee is None:
employee = self._dispatch_call(call, self.supervisors)
employee = self._dispatch_call(call, self.supervisors)
if call.rank == Rank.DIRECTOR or employee is None:
employee = self._dispatch_call(call, self.directors)
employee = self._dispatch_call(call, self.directors)
if employee is None:
self.queued_calls.append(call)
self.queued_calls.append(call)
def _dispatch_call(self, call, employees):
def _dispatch_call(self, call, employees) :
for employee in employees:
if employee.call is None:
employee.take_call(call)
employee.take_call(call)
return employee
return None
def notify_call_escalated(self, call):
def notify_call_escalated(self, call) :
pass
def notify_call_completed(self, call):
def notify_call_completed(self, call) :
pass
def dispatch_queued_call_to_newly_freed_employee(self, call, employee):
def dispatch_queued_call_to_newly_freed_employee(self, call, employee) :
pass

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -57,7 +57,7 @@
"import sys\n",
"\n",
"\n",
"class Suit(Enum):\n",
"class Suit(Enum) :\n",
"\n",
" HEART = 0\n",
" DIAMOND = 1\n",
@@ -65,100 +65,100 @@
" SPADE = 3\n",
"\n",
"\n",
"class Card(metaclass=ABCMeta):\n",
"class Card(metaclass=ABCMeta) :\n",
"\n",
" def __init__(self, value, suit):\n",
" def __init__(self, value, suit) :\n",
" self.value = value\n",
" self.suit = suit\n",
" self.is_available = True\n",
"\n",
" @property\n",
" @abstractmethod\n",
" def value(self):\n",
" def value(self) :\n",
" pass\n",
"\n",
" @value.setter\n",
" @abstractmethod\n",
" def value(self, other):\n",
" def value(self, other) :\n",
" pass\n",
"\n",
"\n",
"class BlackJackCard(Card):\n",
"class BlackJackCard(Card) :\n",
"\n",
" def __init__(self, value, suit):\n",
" super(BlackJackCard, self).__init__(value, suit)\n",
" def __init__(self, value, suit) :\n",
" super(BlackJackCard, self) .__init__(value, suit) \n",
"\n",
" def is_ace(self):\n",
" def is_ace(self) :\n",
" return self._value == 1\n",
"\n",
" def is_face_card(self):\n",
" def is_face_card(self) :\n",
" \"\"\"Jack = 11, Queen = 12, King = 13\"\"\"\n",
" return 10 < self._value <= 13\n",
"\n",
" @property\n",
" def value(self):\n",
" def value(self) :\n",
" if self.is_ace() == 1:\n",
" return 1\n",
" elif self.is_face_card():\n",
" elif self.is_face_card() :\n",
" return 10\n",
" else:\n",
" return self._value\n",
"\n",
" @value.setter\n",
" def value(self, new_value):\n",
" def value(self, new_value) :\n",
" if 1 <= new_value <= 13:\n",
" self._value = new_value\n",
" else:\n",
" raise ValueError('Invalid card value: {}'.format(new_value))\n",
"\n",
"\n",
"class Hand(object):\n",
"class Hand(object) :\n",
"\n",
" def __init__(self, cards):\n",
" def __init__(self, cards) :\n",
" self.cards = cards\n",
"\n",
" def add_card(self, card):\n",
" self.cards.append(card)\n",
" def add_card(self, card) :\n",
" self.cards.append(card) \n",
"\n",
" def score(self):\n",
" def score(self) :\n",
" total_value = 0\n",
" for card in self.cards:\n",
" total_value += card.value\n",
" return total_value\n",
"\n",
"\n",
"class BlackJackHand(Hand):\n",
"class BlackJackHand(Hand) :\n",
"\n",
" BLACKJACK = 21\n",
"\n",
" def __init__(self, cards):\n",
" super(BlackJackHand, self).__init__(cards)\n",
" def __init__(self, cards) :\n",
" super(BlackJackHand, self) .__init__(cards) \n",
"\n",
" def score(self):\n",
" def score(self) :\n",
" min_over = sys.MAXSIZE\n",
" max_under = -sys.MAXSIZE\n",
" for score in self.possible_scores():\n",
" for score in self.possible_scores() :\n",
" if self.BLACKJACK < score < min_over:\n",
" min_over = score\n",
" elif max_under < score <= self.BLACKJACK:\n",
" max_under = score\n",
" return max_under if max_under != -sys.MAXSIZE else min_over\n",
"\n",
" def possible_scores(self):\n",
" def possible_scores(self) :\n",
" \"\"\"Return a list of possible scores, taking Aces into account.\"\"\"\n",
" # ...\n",
"\n",
"\n",
"class Deck(object):\n",
"class Deck(object) :\n",
"\n",
" def __init__(self, cards):\n",
" def __init__(self, cards) :\n",
" self.cards = cards\n",
" self.deal_index = 0\n",
"\n",
" def remaining_cards(self):\n",
" def remaining_cards(self) :\n",
" return len(self.cards) - deal_index\n",
"\n",
" def deal_card():\n",
" def deal_card() :\n",
" try:\n",
" card = self.cards[self.deal_index]\n",
" card.is_available = False\n",
@@ -167,7 +167,7 @@
" return None\n",
" return card\n",
"\n",
" def shuffle(self): # ..."
" def shuffle(self) : # ..."
]
}
],

View File

@@ -3,7 +3,7 @@ from enum import Enum
import sys
class Suit(Enum):
class Suit(Enum) :
HEART = 0
DIAMOND = 1
@@ -11,100 +11,100 @@ class Suit(Enum):
SPADE = 3
class Card(metaclass=ABCMeta):
class Card(metaclass=ABCMeta) :
def __init__(self, value, suit):
def __init__(self, value, suit) :
self.value = value
self.suit = suit
self.is_available = True
@property
@abstractmethod
def value(self):
def value(self) :
pass
@value.setter
@abstractmethod
def value(self, other):
def value(self, other) :
pass
class BlackJackCard(Card):
class BlackJackCard(Card) :
def __init__(self, value, suit):
super(BlackJackCard, self).__init__(value, suit)
def __init__(self, value, suit) :
super(BlackJackCard, self) .__init__(value, suit)
def is_ace(self):
def is_ace(self) :
return True if self._value == 1 else False
def is_face_card(self):
def is_face_card(self) :
"""Jack = 11, Queen = 12, King = 13"""
return True if 10 < self._value <= 13 else False
@property
def value(self):
def value(self) :
if self.is_ace() == 1:
return 1
elif self.is_face_card():
elif self.is_face_card() :
return 10
else:
return self._value
@value.setter
def value(self, new_value):
def value(self, new_value) :
if 1 <= new_value <= 13:
self._value = new_value
else:
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
def add_card(self, card):
self.cards.append(card)
def add_card(self, card) :
self.cards.append(card)
def score(self):
def score(self) :
total_value = 0
for card in self.cards:
total_value += card.value
return total_value
class BlackJackHand(Hand):
class BlackJackHand(Hand) :
BLACKJACK = 21
def __init__(self, cards):
super(BlackJackHand, self).__init__(cards)
def __init__(self, cards) :
super(BlackJackHand, self) .__init__(cards)
def score(self):
def score(self) :
min_over = sys.MAXSIZE
max_under = -sys.MAXSIZE
for score in self.possible_scores():
for score in self.possible_scores() :
if self.BLACKJACK < score < min_over:
min_over = score
elif max_under < score <= self.BLACKJACK:
max_under = score
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."""
pass
class Deck(object):
class Deck(object) :
def __init__(self, cards):
def __init__(self, cards) :
self.cards = cards
self.deal_index = 0
def remaining_cards(self):
def remaining_cards(self) :
return len(self.cards) - self.deal_index
def deal_card(self):
def deal_card(self) :
try:
card = self.cards[self.deal_index]
card.is_available = False
@@ -113,5 +113,5 @@ class Deck(object):
return None
return card
def shuffle(self):
def shuffle(self) :
pass

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -56,44 +56,44 @@
],
"source": [
"%%writefile hash_map.py\n",
"class Item(object):\n",
"class Item(object) :\n",
"\n",
" def __init__(self, key, value):\n",
" def __init__(self, key, value) :\n",
" self.key = key\n",
" self.value = value\n",
"\n",
"\n",
"class HashTable(object):\n",
"class HashTable(object) :\n",
"\n",
" def __init__(self, size):\n",
" def __init__(self, size) :\n",
" self.size = size\n",
" self.table = [[] for _ in range(self.size)]\n",
" self.table = [[] for _ in range(self.size) ]\n",
"\n",
" def _hash_function(self, key):\n",
" def _hash_function(self, key) :\n",
" return key % self.size\n",
"\n",
" def set(self, key, value):\n",
" hash_index = self._hash_function(key)\n",
" def set(self, key, value) :\n",
" hash_index = self._hash_function(key) \n",
" for item in self.table[hash_index]:\n",
" if item.key == key:\n",
" item.value = value\n",
" return\n",
" self.table[hash_index].append(Item(key, value))\n",
"\n",
" def get(self, key):\n",
" hash_index = self._hash_function(key)\n",
" def get(self, key) :\n",
" hash_index = self._hash_function(key) \n",
" for item in self.table[hash_index]:\n",
" if item.key == key:\n",
" return item.value\n",
" raise KeyError('Key not found')\n",
" raise KeyError('Key not found') \n",
"\n",
" def remove(self, key):\n",
" hash_index = self._hash_function(key)\n",
" for index, item in enumerate(self.table[hash_index]):\n",
" def remove(self, key) :\n",
" hash_index = self._hash_function(key) \n",
" for index, item in enumerate(self.table[hash_index]) :\n",
" if item.key == key:\n",
" del self.table[hash_index][index]\n",
" return\n",
" raise KeyError('Key not found')"
" raise KeyError('Key not found') "
]
}
],

View File

@@ -1,38 +1,38 @@
class Item(object):
class Item(object) :
def __init__(self, key, value):
def __init__(self, key, value) :
self.key = key
self.value = value
class HashTable(object):
class HashTable(object) :
def __init__(self, size):
def __init__(self, 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
def set(self, key, value):
hash_index = self._hash_function(key)
def set(self, key, value) :
hash_index = self._hash_function(key)
for item in self.table[hash_index]:
if item.key == key:
item.value = value
return
self.table[hash_index].append(Item(key, value))
def get(self, key):
hash_index = self._hash_function(key)
def get(self, key) :
hash_index = self._hash_function(key)
for item in self.table[hash_index]:
if item.key == key:
return item.value
raise KeyError('Key not found')
raise KeyError('Key not found')
def remove(self, key):
hash_index = self._hash_function(key)
for index, item in enumerate(self.table[hash_index]):
def remove(self, key) :
hash_index = self._hash_function(key)
for index, item in enumerate(self.table[hash_index]) :
if item.key == key:
del self.table[hash_index][index]
return
raise KeyError('Key not found')
raise KeyError('Key not found')

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -52,67 +52,67 @@
],
"source": [
"%%writefile lru_cache.py\n",
"class Node(object):\n",
"class Node(object) :\n",
"\n",
" def __init__(self, results):\n",
" def __init__(self, results) :\n",
" self.results = results\n",
" self.prev = None\n",
" self.next = None\n",
"\n",
"\n",
"class LinkedList(object):\n",
"class LinkedList(object) :\n",
"\n",
" def __init__(self):\n",
" def __init__(self) :\n",
" self.head = None\n",
" self.tail = None\n",
"\n",
" def move_to_front(self, node): # ...\n",
" def append_to_front(self, node): # ...\n",
" def remove_from_tail(self): # ...\n",
" def move_to_front(self, node) : # ...\n",
" def append_to_front(self, node) : # ...\n",
" def remove_from_tail(self) : # ...\n",
"\n",
"\n",
"class Cache(object):\n",
"class Cache(object) :\n",
"\n",
" def __init__(self, MAX_SIZE):\n",
" def __init__(self, MAX_SIZE) :\n",
" self.MAX_SIZE = MAX_SIZE\n",
" self.size = 0\n",
" self.lookup = {} # key: query, value: node\n",
" self.linked_list = LinkedList()\n",
" self.linked_list = LinkedList() \n",
"\n",
" def get(self, query)\n",
" def get(self, query) \n",
" \"\"\"Get the stored query result from the cache.\n",
" \n",
" Accessing a node updates its position to the front of the LRU list.\n",
" \"\"\"\n",
" node = self.lookup.get(query)\n",
" node = self.lookup.get(query) \n",
" if node is None:\n",
" return None\n",
" self.linked_list.move_to_front(node)\n",
" self.linked_list.move_to_front(node) \n",
" return node.results\n",
"\n",
" def set(self, results, query):\n",
" def set(self, results, query) :\n",
" \"\"\"Set the result for the given query key in the cache.\n",
" \n",
" When updating an entry, updates its position to the front of the LRU list.\n",
" If the entry is new and the cache is at capacity, removes the oldest entry\n",
" before the new entry is added.\n",
" \"\"\"\n",
" node = self.lookup.get(query)\n",
" node = self.lookup.get(query) \n",
" if node is not None:\n",
" # Key exists in cache, update the value\n",
" node.results = results\n",
" self.linked_list.move_to_front(node)\n",
" self.linked_list.move_to_front(node) \n",
" else:\n",
" # Key does not exist in cache\n",
" if self.size == self.MAX_SIZE:\n",
" # Remove the oldest entry from the linked list and lookup\n",
" self.lookup.pop(self.linked_list.tail.query, None)\n",
" self.linked_list.remove_from_tail()\n",
" self.lookup.pop(self.linked_list.tail.query, None) \n",
" self.linked_list.remove_from_tail() \n",
" else:\n",
" self.size += 1\n",
" # Add the new key and value\n",
" new_node = Node(results)\n",
" self.linked_list.append_to_front(new_node)\n",
" new_node = Node(results) \n",
" self.linked_list.append_to_front(new_node) \n",
" self.lookup[query] = new_node"
]
}

View File

@@ -1,66 +1,66 @@
class Node(object):
class Node(object) :
def __init__(self, results):
def __init__(self, results) :
self.results = results
self.next = next
class LinkedList(object):
class LinkedList(object) :
def __init__(self):
def __init__(self) :
self.head = None
self.tail = None
def move_to_front(self, node):
def move_to_front(self, node) :
pass
def append_to_front(self, node):
def append_to_front(self, node) :
pass
def remove_from_tail(self):
def remove_from_tail(self) :
pass
class Cache(object):
class Cache(object) :
def __init__(self, MAX_SIZE):
def __init__(self, MAX_SIZE) :
self.MAX_SIZE = MAX_SIZE
self.size = 0
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.
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:
return None
self.linked_list.move_to_front(node)
self.linked_list.move_to_front(node)
return node.results
def set(self, results, query):
def set(self, results, query) :
"""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.
If the entry is new and the cache is at capacity, removes the oldest entry
before the new entry is added.
"""
node = self.lookup.get(query)
node = self.lookup.get(query)
if node is not None:
# Key exists in cache, update the value
node.results = results
self.linked_list.move_to_front(node)
self.linked_list.move_to_front(node)
else:
# Key does not exist in cache
if self.size == self.MAX_SIZE:
# Remove the oldest entry from the linked list and lookup
self.lookup.pop(self.linked_list.tail.query, None)
self.linked_list.remove_from_tail()
self.lookup.pop(self.linked_list.tail.query, None)
self.linked_list.remove_from_tail()
else:
self.size += 1
# Add the new key and value
new_node = Node(results)
self.linked_list.append_to_front(new_node)
new_node = Node(results)
self.linked_list.append_to_front(new_node)
self.lookup[query] = new_node

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -67,21 +67,21 @@
"from abc import ABCMeta\n",
"\n",
"\n",
"class UserService(object):\n",
"class UserService(object) :\n",
"\n",
" def __init__(self):\n",
" def __init__(self) :\n",
" self.users_by_id = {} # key: user id, value: User\n",
"\n",
" def add_user(self, user_id, name, pass_hash): # ...\n",
" def remove_user(self, user_id): # ...\n",
" def add_friend_request(self, from_user_id, to_user_id): # ...\n",
" def approve_friend_request(self, from_user_id, to_user_id): # ...\n",
" def reject_friend_request(self, from_user_id, to_user_id): # ...\n",
" def add_user(self, user_id, name, pass_hash) : # ...\n",
" def remove_user(self, user_id) : # ...\n",
" def add_friend_request(self, from_user_id, to_user_id) : # ...\n",
" def approve_friend_request(self, from_user_id, to_user_id) : # ...\n",
" def reject_friend_request(self, from_user_id, to_user_id) : # ...\n",
"\n",
"\n",
"class User(object):\n",
"class User(object) :\n",
"\n",
" def __init__(self, user_id, name, pass_hash):\n",
" def __init__(self, user_id, name, pass_hash) :\n",
" self.user_id = user_id\n",
" self.name = name\n",
" self.pass_hash = pass_hash\n",
@@ -91,54 +91,54 @@
" self.received_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest\n",
" self.sent_friend_requests_by_friend_id = {} # key: friend id, value: AddRequest\n",
"\n",
" def message_user(self, friend_id, message): # ...\n",
" def message_group(self, group_id, message): # ...\n",
" def send_friend_request(self, friend_id): # ...\n",
" def receive_friend_request(self, friend_id): # ...\n",
" def approve_friend_request(self, friend_id): # ...\n",
" def reject_friend_request(self, friend_id): # ...\n",
" def message_user(self, friend_id, message) : # ...\n",
" def message_group(self, group_id, message) : # ...\n",
" def send_friend_request(self, friend_id) : # ...\n",
" def receive_friend_request(self, friend_id) : # ...\n",
" def approve_friend_request(self, friend_id) : # ...\n",
" def reject_friend_request(self, friend_id) : # ...\n",
"\n",
"\n",
"class Chat(metaclass=ABCMeta):\n",
"class Chat(metaclass=ABCMeta) :\n",
"\n",
" def __init__(self, chat_id):\n",
" def __init__(self, chat_id) :\n",
" self.chat_id = chat_id\n",
" self.users = []\n",
" self.messages = []\n",
"\n",
"\n",
"class PrivateChat(Chat):\n",
"class PrivateChat(Chat) :\n",
"\n",
" def __init__(self, first_user, second_user):\n",
" super(PrivateChat, self).__init__()\n",
" self.users.append(first_user)\n",
" self.users.append(second_user)\n",
" def __init__(self, first_user, second_user) :\n",
" super(PrivateChat, self) .__init__() \n",
" self.users.append(first_user) \n",
" self.users.append(second_user) \n",
"\n",
"\n",
"class GroupChat(Chat):\n",
"class GroupChat(Chat) :\n",
"\n",
" def add_user(self, user): # ...\n",
" def remove_user(self, user): # ... \n",
" def add_user(self, user) : # ...\n",
" def remove_user(self, user) : # ... \n",
"\n",
"\n",
"class Message(object):\n",
"class Message(object) :\n",
"\n",
" def __init__(self, message_id, message, timestamp):\n",
" def __init__(self, message_id, message, timestamp) :\n",
" self.message_id = message_id\n",
" self.message = message\n",
" self.timestamp = timestamp\n",
"\n",
"\n",
"class AddRequest(object):\n",
"class AddRequest(object) :\n",
"\n",
" def __init__(self, from_user_id, to_user_id, request_status, timestamp):\n",
" def __init__(self, from_user_id, to_user_id, request_status, timestamp) :\n",
" self.from_user_id = from_user_id\n",
" self.to_user_id = to_user_id\n",
" self.request_status = request_status\n",
" self.timestamp = timestamp\n",
"\n",
"\n",
"class RequestStatus(Enum):\n",
"class RequestStatus(Enum) :\n",
"\n",
" UNREAD = 0\n",
" READ = 1\n",

View File

@@ -2,30 +2,30 @@ from abc import ABCMeta
from enum import Enum
class UserService(object):
class UserService(object) :
def __init__(self):
def __init__(self) :
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) :
pass
def remove_user(self, user_id):
def remove_user(self, user_id) :
pass
def add_friend_request(self, from_user_id, to_user_id):
def add_friend_request(self, from_user_id, to_user_id) :
pass
def approve_friend_request(self, from_user_id, to_user_id):
def approve_friend_request(self, from_user_id, to_user_id) :
pass
def reject_friend_request(self, from_user_id, to_user_id):
def reject_friend_request(self, from_user_id, to_user_id) :
pass
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.name = name
self.pass_hash = pass_hash
@@ -35,68 +35,68 @@ class User(object):
self.received_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) :
pass
def message_group(self, group_id, message):
def message_group(self, group_id, message) :
pass
def send_friend_request(self, friend_id):
def send_friend_request(self, friend_id) :
pass
def receive_friend_request(self, friend_id):
def receive_friend_request(self, friend_id) :
pass
def approve_friend_request(self, friend_id):
def approve_friend_request(self, friend_id) :
pass
def reject_friend_request(self, friend_id):
def reject_friend_request(self, friend_id) :
pass
class Chat(metaclass=ABCMeta):
class Chat(metaclass=ABCMeta) :
def __init__(self, chat_id):
def __init__(self, chat_id) :
self.chat_id = chat_id
self.users = []
self.messages = []
class PrivateChat(Chat):
class PrivateChat(Chat) :
def __init__(self, first_user, second_user):
super(PrivateChat, self).__init__()
self.users.append(first_user)
self.users.append(second_user)
def __init__(self, first_user, second_user) :
super(PrivateChat, self) .__init__()
self.users.append(first_user)
self.users.append(second_user)
class GroupChat(Chat):
class GroupChat(Chat) :
def add_user(self, user):
def add_user(self, user) :
pass
def remove_user(self, user):
def remove_user(self, user) :
pass
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 = message
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.to_user_id = to_user_id
self.request_status = request_status
self.timestamp = timestamp
class RequestStatus(Enum):
class RequestStatus(Enum) :
UNREAD = 0
READ = 1

View File

@@ -4,7 +4,7 @@
"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)."
"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) ."
]
},
{
@@ -59,107 +59,107 @@
"from abc import ABCMeta, abstractmethod\n",
"\n",
"\n",
"class VehicleSize(Enum):\n",
"class VehicleSize(Enum) :\n",
"\n",
" MOTORCYCLE = 0\n",
" COMPACT = 1\n",
" LARGE = 2\n",
"\n",
"\n",
"class Vehicle(metaclass=ABCMeta):\n",
"class Vehicle(metaclass=ABCMeta) :\n",
"\n",
" def __init__(self, vehicle_size, license_plate, spot_size):\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 = spot_size\n",
" self.spots_taken = []\n",
"\n",
" def clear_spots(self):\n",
" def clear_spots(self) :\n",
" for spot in self.spots_taken:\n",
" spot.remove_vehicle(self)\n",
" spot.remove_vehicle(self) \n",
" self.spots_taken = []\n",
"\n",
" def take_spot(self, spot):\n",
" self.spots_taken.append(spot)\n",
" def take_spot(self, spot) :\n",
" self.spots_taken.append(spot) \n",
"\n",
" @abstractmethod\n",
" def can_fit_in_spot(self, spot):\n",
" def can_fit_in_spot(self, spot) :\n",
" pass\n",
"\n",
"\n",
"class Motorcycle(Vehicle):\n",
"class Motorcycle(Vehicle) :\n",
"\n",
" def __init__(self, license_plate):\n",
" super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1)\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",
" def can_fit_in_spot(self, spot) :\n",
" return True\n",
"\n",
"\n",
"class Car(Vehicle):\n",
"class Car(Vehicle) :\n",
"\n",
" def __init__(self, license_plate):\n",
" super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1)\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",
" 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",
"class Bus(Vehicle) :\n",
"\n",
" def __init__(self, license_plate):\n",
" super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5)\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",
" def can_fit_in_spot(self, spot) :\n",
" return True if spot.size == LARGE else False\n",
"\n",
"\n",
"class ParkingLot(object):\n",
"class ParkingLot(object) :\n",
"\n",
" def __init__(self, num_levels):\n",
" def __init__(self, num_levels) :\n",
" self.num_levels = num_levels\n",
" self.levels = []\n",
"\n",
" def park_vehicle(self, vehicle):\n",
" def park_vehicle(self, vehicle) :\n",
" for level in levels:\n",
" if level.park_vehicle(vehicle):\n",
" if level.park_vehicle(vehicle) :\n",
" return True\n",
" return False\n",
"\n",
"\n",
"class Level(object):\n",
"class Level(object) :\n",
"\n",
" SPOTS_PER_ROW = 10\n",
"\n",
" def __init__(self, floor, total_spots):\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",
" def spot_freed(self) :\n",
" self.available_spots += 1\n",
"\n",
" def park_vehicle(self, vehicle):\n",
" spot = self._find_available_spot(vehicle)\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",
" spot.park_vehicle(vehicle) \n",
" return spot\n",
"\n",
" def _find_available_spot(self, vehicle):\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",
" 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",
"class ParkingSpot(object) :\n",
"\n",
" def __init__(self, level, row, spot_number, spot_size, vehicle_size):\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",
@@ -167,16 +167,16 @@
" self.vehicle_size = vehicle_size\n",
" self.vehicle = None\n",
"\n",
" def is_available(self):\n",
" def is_available(self) :\n",
" return True if self.vehicle is None else False\n",
"\n",
" def can_fit_vehicle(self, vehicle):\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",
" return vehicle.can_fit_in_spot(self) \n",
"\n",
" def park_vehicle(self, vehicle): # ...\n",
" def remove_vehicle(self): # ..."
" def park_vehicle(self, vehicle) : # ...\n",
" def remove_vehicle(self) : # ..."
]
}
],

View File

@@ -2,107 +2,107 @@ from abc import ABCMeta, abstractmethod
from enum import Enum
class VehicleSize(Enum):
class VehicleSize(Enum) :
MOTORCYCLE = 0
COMPACT = 1
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.license_plate = license_plate
self.spot_size
self.spots_taken = []
def clear_spots(self):
def clear_spots(self) :
for spot in self.spots_taken:
spot.remove_vehicle(self)
spot.remove_vehicle(self)
self.spots_taken = []
def take_spot(self, spot):
self.spots_taken.append(spot)
def take_spot(self, spot) :
self.spots_taken.append(spot)
@abstractmethod
def can_fit_in_spot(self, spot):
def can_fit_in_spot(self, spot) :
pass
class Motorcycle(Vehicle):
class Motorcycle(Vehicle) :
def __init__(self, license_plate):
super(Motorcycle, self).__init__(VehicleSize.MOTORCYCLE, license_plate, spot_size=1)
def __init__(self, license_plate) :
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
class Car(Vehicle):
class Car(Vehicle) :
def __init__(self, license_plate):
super(Car, self).__init__(VehicleSize.COMPACT, license_plate, spot_size=1)
def __init__(self, license_plate) :
super(Car, self) .__init__(VehicleSize.COMPACT, license_plate, spot_size=1)
def can_fit_in_spot(self, spot):
return spot.size in (VehicleSize.LARGE, VehicleSize.COMPACT)
def can_fit_in_spot(self, spot) :
return spot.size in (VehicleSize.LARGE, VehicleSize.COMPACT)
class Bus(Vehicle):
class Bus(Vehicle) :
def __init__(self, license_plate):
super(Bus, self).__init__(VehicleSize.LARGE, license_plate, spot_size=5)
def __init__(self, license_plate) :
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 spot.size == VehicleSize.LARGE
class ParkingLot(object):
class ParkingLot(object) :
def __init__(self, num_levels):
def __init__(self, num_levels) :
self.num_levels = num_levels
self.levels = [] # List of Levels
def park_vehicle(self, vehicle):
def park_vehicle(self, vehicle) :
for level in self.levels:
if level.park_vehicle(vehicle):
if level.park_vehicle(vehicle) :
return True
return False
class Level(object):
class Level(object) :
SPOTS_PER_ROW = 10
def __init__(self, floor, total_spots):
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):
def spot_freed(self) :
self.available_spots += 1
def park_vehicle(self, vehicle):
spot = self._find_available_spot(vehicle)
def park_vehicle(self, vehicle) :
spot = self._find_available_spot(vehicle)
if spot is None:
return None
else:
spot.park_vehicle(vehicle)
spot.park_vehicle(vehicle)
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"""
pass
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."""
pass
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.row = row
self.spot_number = spot_number
@@ -110,16 +110,16 @@ class ParkingSpot(object):
self.vehicle_size = vehicle_size
self.vehicle = None
def is_available(self):
def is_available(self) :
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:
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) :
pass
def remove_vehicle(self):
def remove_vehicle(self) :
pass