Skip to content

Commit 1e7ddeb

Browse files
Added rind buffer algorithm in python 231
1 parent 7a288a4 commit 1e7ddeb

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.metals
2+
__pycache__/

README.md

+58
Original file line numberDiff line numberDiff line change
@@ -2328,6 +2328,64 @@ In order to achieve greater coverage and encourage more people to contribute to
23282328
</a>
23292329
</td>
23302330
</tr>
2331+
<tr>
2332+
<td><a href="https://en.wikipedia.org/wiki/Circular_buffer">Ring Buffer</a></td>
2333+
<td> <!-- C -->
2334+
<a href="./CONTRIBUTING.md">
2335+
<img align="center" height="25" src="./logos/github.svg" />
2336+
</a>
2337+
</td>
2338+
<td> <!-- C++ -->
2339+
<a href="./CONTRIBUTING.md">
2340+
<img align="center" height="25" src="./logos/github.svg" />
2341+
</a>
2342+
</td>
2343+
<td> <!-- Java -->
2344+
<a href="./CONTRIBUTING.md">
2345+
<img align="center" height="25" src="./logos/github.svg" />
2346+
</a>
2347+
</td>
2348+
<td> <!-- Python -->
2349+
<a href="./src/python/ring_buffer.py">
2350+
<img align="center" height="25" src="./logos/python.svg" />
2351+
</a>
2352+
</td>
2353+
<td> <!-- Go -->
2354+
<a href="./CONTRIBUTING.md">
2355+
<img align="center" height="25" src="./logos/github.svg" />
2356+
</a>
2357+
</td>
2358+
<td> <!-- Ruby -->
2359+
<a href="./CONTRIBUTING.md">
2360+
<img align="center" height="25" src="./logos/github.svg" />
2361+
</a>
2362+
</td>
2363+
<td> <!-- JavaScript -->
2364+
<a href="./CONTRIBUTING.md">
2365+
<img align="center" height="25" src="./logos/github.svg" />
2366+
</a>
2367+
</td>
2368+
<td> <!-- Swift -->
2369+
<a href="./CONTRIBUTING.md">
2370+
<img align="center" height="25" src="./logos/github.svg" />
2371+
</a>
2372+
</td>
2373+
<td> <!-- Rust -->
2374+
<a href="./CONTRIBUTING.md">
2375+
<img align="center" height="25" src="./logos/github.svg" />
2376+
</a>
2377+
</td>
2378+
<td> <!-- Scala -->
2379+
<a href="./CONTRIBUTING.md">
2380+
<img align="center" height="25" src="./logos/github.svg" />
2381+
</a>
2382+
</td>
2383+
<td> <!-- Kotlin -->
2384+
<a href="./CONTRIBUTING.md">
2385+
<img align="center" height="25" src="./logos/github.svg" />
2386+
</a>
2387+
</td>
2388+
</tr>
23312389
<tr>
23322390
<td><a href="https://en.wikipedia.org/wiki/Hash_table">Hash Table</a></td>
23332391
<td> <!-- C -->

src/python/ring_buffer.py

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from typing import Generic, TypeVar
2+
3+
T = TypeVar("T")
4+
5+
6+
class RingBuffer(Generic[T]):
7+
def __init__(self, capacity: int) -> None:
8+
self._capacity = capacity
9+
self._init_buffer()
10+
11+
def __str__(self) -> str:
12+
if self.is_empty():
13+
return "[]"
14+
15+
if self._tail > self._head:
16+
buffer_state = self._buffer[self._head : self._tail]
17+
else:
18+
buffer_state = self._buffer[self._head :] + self._buffer[: self._tail]
19+
return str(buffer_state)
20+
21+
def __repr__(self) -> str:
22+
return self.__str__()
23+
24+
def __len__(self) -> int:
25+
return self._size
26+
27+
def _init_buffer(self) -> None:
28+
self._buffer = [None] * self._capacity
29+
self._head = 0
30+
self._tail = 0
31+
self._size = 0
32+
33+
def clear(self) -> None:
34+
self._init_buffer()
35+
36+
def push(self, item: T) -> None:
37+
if self.is_full():
38+
raise IndexError("Ring buffer is full")
39+
40+
self._buffer[self._tail] = item
41+
self._tail = (self._tail + 1) % self._capacity
42+
self._size = min(self._size + 1, self._capacity)
43+
44+
def get(self) -> T:
45+
if self.is_empty():
46+
raise IndexError("Ring buffer is empty")
47+
48+
item = self._buffer[self._head]
49+
self._head = (self._head + 1) % self._capacity
50+
self._size -= 1
51+
return item
52+
53+
def is_full(self) -> bool:
54+
return self._size == self._capacity
55+
56+
def is_empty(self) -> bool:
57+
return self._size == 0
58+
59+
60+
if __name__ == "__main__":
61+
import unittest
62+
63+
class TestRingBuffer(unittest.TestCase):
64+
def test_push(self):
65+
ring_buffer = RingBuffer[int](3)
66+
ring_buffer.push(7)
67+
ring_buffer.push(3)
68+
self.assertEqual("[7, 3]", str(ring_buffer))
69+
ring_buffer.push(10)
70+
self.assertEqual("[7, 3, 10]", str(ring_buffer))
71+
72+
def test_get(self):
73+
ring_buffer = RingBuffer[int](3)
74+
ring_buffer.push(17)
75+
ring_buffer.push(35)
76+
self.assertEqual(17, ring_buffer.get())
77+
self.assertEqual(35, ring_buffer.get())
78+
79+
def test_clear(self):
80+
ring_buffer = RingBuffer[int](3)
81+
ring_buffer.push(6)
82+
ring_buffer.push(11)
83+
self.assertEqual("[6, 11]", str(ring_buffer))
84+
ring_buffer.clear()
85+
self.assertEqual("[]", str(ring_buffer))
86+
self.assertEqual(0, len(ring_buffer))
87+
88+
def test_push_with_full_error(self):
89+
ring_buffer = RingBuffer[int](1)
90+
ring_buffer.push(7)
91+
self.assertRaises(IndexError, ring_buffer.push, 9)
92+
93+
ring_buffer = RingBuffer[int](2)
94+
ring_buffer.push(23)
95+
ring_buffer.push(14)
96+
self.assertRaises(IndexError, ring_buffer.push, 11)
97+
98+
def test_get_with_empty_error(self):
99+
ring_buffer = RingBuffer[int](1)
100+
self.assertRaises(IndexError, ring_buffer.get)
101+
ring_buffer.push(15)
102+
ring_buffer.get()
103+
self.assertRaises(IndexError, ring_buffer.get)
104+
105+
def test_size(self):
106+
ring_buffer = RingBuffer[int](3)
107+
ring_buffer.push(5)
108+
self.assertEqual(1, len(ring_buffer))
109+
ring_buffer.push(3)
110+
self.assertEqual(2, len(ring_buffer))
111+
ring_buffer.get()
112+
self.assertEqual(1, len(ring_buffer))
113+
114+
def test_str(self):
115+
ring_buffer = RingBuffer[int](3)
116+
self.assertEqual("[]", str(ring_buffer))
117+
ring_buffer.push(10)
118+
self.assertEqual("[10]", str(ring_buffer))
119+
ring_buffer.get()
120+
ring_buffer.push(11)
121+
ring_buffer.push(9)
122+
self.assertEqual("[11, 9]", str(ring_buffer))
123+
ring_buffer.push(7)
124+
self.assertEqual("[11, 9, 7]", str(ring_buffer))
125+
126+
def test_with_str_type(self):
127+
ring_buffer = RingBuffer[str](3)
128+
ring_buffer.push("mug")
129+
ring_buffer.push("cup")
130+
self.assertEqual("['mug', 'cup']", str(ring_buffer))
131+
132+
suite = unittest.TestLoader().loadTestsFromTestCase(TestRingBuffer)
133+
unittest.TextTestRunner(verbosity=2).run(suite)

0 commit comments

Comments
 (0)