This commit is contained in:
Sarath Sadasivan Pillai 2023-03-29 22:16:18 +02:00 committed by GitHub
commit 034e465238
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 273 additions and 1 deletions

View File

@ -366,7 +366,7 @@ Check out the following links to get a better idea of what to expect:
| Design a deck of cards | [Solution](solutions/object_oriented_design/deck_of_cards/deck_of_cards.ipynb) |
| Design a parking lot | [Solution](solutions/object_oriented_design/parking_lot/parking_lot.ipynb) |
| Design a chat server | [Solution](solutions/object_oriented_design/online_chat/online_chat.ipynb) |
| Design a circular array | [Contribute](#contributing) |
| Design a circular array | [Solution](solutions/object_oriented_design/circular_array/circular_array.ipynb) |
| Add an object-oriented design question | [Contribute](#contributing) |
## System design topics: start here

View File

@ -0,0 +1,222 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook was prepared by [Sarath S Pillai](https://github.com/sarathsp06). Source and license info is on [GitHub](https://github.com/donnemartin/system-design-primer-primer)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Design a circular array"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Constraints and assumptions\n",
"\n",
"* For simplicity, are the keys integers only?\n",
" * Yes\n",
"* Can we assume this fits memory?\n",
" * Yes\n",
"* Is array size fixed\n",
" * Yes\n",
"* What happens to deleted indexes\n",
" * None onget request"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Circular array Interface\n",
"* \\[idx\\]\n",
" * get item on idx ,assuming circular array\n",
" * any idx value is taken as modulo of itself with size\n",
" * negative idx is not permitted\n",
"* len\n",
" * length is always length of current valid entries\n",
"* repr\n",
" * the circular aray is printed with values in order\n",
" * logical order is maintained not how it is stored\n",
"* push\n",
" * pushed item to end of queue\n",
" * throws exception if capcity is filled , len == capcaity\n",
"* pop\n",
" * pop an item from start of array\n",
" * throws exception if \n",
"* capacity\n",
" * returns initial size of array "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Solution"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Overwriting circular_array.py\n"
]
}
],
"source": [
"%%writefile circular_array.py\n",
"class CircularArray(object):\n",
" def __init__(self, size):\n",
" if size <= 0:\n",
" raise ValueError(\"Size has to be non zero positive number\")\n",
" self.size = size\n",
" self.array = self.size *[None]\n",
" self.start = self.end = None\n",
" \n",
" def capacity(self):\n",
" return self.size\n",
" \n",
" def __len__(self):\n",
" if self.start is None:\n",
" return 0\n",
" return (self.end - self.start + self.size ) % self.size + 1\n",
" \n",
" def __getitem__(self, key):\n",
" if key < 0:\n",
" raise ValueError(\"Key has to be a positive number\")\n",
" if self.start is None:\n",
" return None\n",
" index = (key + self.start) % self.size\n",
" return self.array[index]\n",
" \n",
" def push(self, value):\n",
" if self.start is None:\n",
" self.start = self.end = 0\n",
" else:\n",
" index = (self.end + 1) % self.size\n",
" if index == self.start:\n",
" raise IndexError(\"Push to full array \")\n",
" self.end = index\n",
" self.array[self.end] = value\n",
" \n",
" def __repr__(self):\n",
" if self.start is None:\n",
" return '[]'\n",
" if self.start < self.end:\n",
" return repr(self.array[self.start:self.end+1])\n",
" return repr(self.array[self.start:]+self.array[:self.end+1])\n",
" \n",
" def pop(self):\n",
" if self.start is None:\n",
" raise RuntimeException(\"Pop on nil array\")\n",
" value = self.array[self.start]\n",
" if self.start == self.end:\n",
" self.start = self.end = None\n",
" return value\n",
" self.start = (self.start + 1) % self.size\n",
" return value"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test\n",
"\n",
"Here are basic test cases to illustrate the features"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from circular_array import CircularArray\n",
"# create a circular array of 10 elements\n",
"ca = CircularArray(10);\n",
"assert ca.capacity() == 10\n",
"\n",
"#push 4 items\n",
"ca.push(1)\n",
"ca.push(2)\n",
"ca.push(3)\n",
"ca.push(4)\n",
"assert ca.capacity() == 10\n",
"\n",
"#pop and check 3 elements\n",
"assert ca.pop() == 1\n",
"assert ca.pop() == 2\n",
"assert ca.pop() == 3\n",
"assert len(ca) == 1\n",
"\n",
"#push 4 more elements\n",
"ca.push(5)\n",
"ca.push(6)\n",
"ca.push(7)\n",
"ca.push(8)\n",
"assert len(ca) == 5\n",
"\n",
"#check getitem function for proper indexing and pop 2 elements\n",
"assert ca[0] == 4\n",
"assert ca.pop() == 4\n",
"assert ca[0] == 5\n",
"assert ca[10] == 5\n",
"assert ca.pop() == 5\n",
"assert len(ca) == 3\n",
"#push 7 more items \n",
"ca.push(9)\n",
"ca.push(10)\n",
"ca.push(11)\n",
"ca.push(12)\n",
"ca.push(13)\n",
"ca.push(14)\n",
"ca.push(15)\n",
"assert len(ca) == 10\n",
"assert ca.capacity() == 10\n",
"assert repr(ca) == '[6, 7, 8, 9, 10, 11, 12, 13, 14, 15]'\n",
"assert ca[1] == 7\n",
"assert ca[11] == 7"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.6.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@ -0,0 +1,50 @@
class CircularArray(object):
def __init__(self, size):
if size <= 0:
raise ValueError("Size has to be non zero positive number")
self.size = size
self.array = self.size *[None]
self.start = self.end = None
def capacity(self):
return self.size
def __len__(self):
if self.start is None:
return 0
return (self.end - self.start + self.size ) % self.size + 1
def __getitem__(self, key):
if key < 0:
raise ValueError("Key has to be a positive number")
if self.start is None:
return None
index = (key + self.start) % self.size
return self.array[index]
def push(self, value):
if self.start is None:
self.start = self.end = 0
else:
index = (self.end + 1) % self.size
if index == self.start:
raise IndexError("Push to full array ")
self.end = index
self.array[self.end] = value
def __repr__(self):
if self.start is None:
return '[]'
if self.start < self.end:
return repr(self.array[self.start:self.end+1])
return repr(self.array[self.start:]+self.array[:self.end+1])
def pop(self):
if self.start is None:
raise RuntimeException("Pop on nil array")
value = self.array[self.start]
if self.start == self.end:
self.start = self.end = None
return value
self.start = (self.start + 1) % self.size
return value