Skip to content

Commit 2fe690f

Browse files
caching
1 parent e77af65 commit 2fe690f

8 files changed

+298
-1
lines changed

0x01-caching/0-basic_cache.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/python3
2+
"""
3+
Module 0-basic_cache
4+
"""
5+
from base_caching import BaseCaching
6+
7+
8+
class BasicCache(BaseCaching):
9+
"""
10+
Overrides put() nad self()
11+
from parent
12+
"""
13+
14+
def put(self, key, item):
15+
"""Add an item in the cache
16+
"""
17+
if key and item:
18+
self.cache_data[key] = item
19+
20+
def get(self, key):
21+
"""Get an item by key
22+
"""
23+
value = self.cache_data.get(key)
24+
return value

0x01-caching/1-fifo_cache.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/python3
2+
"""
3+
Module 1-fifo_cache.py
4+
"""
5+
from base_caching import BaseCaching
6+
from collections import deque
7+
8+
9+
class FIFOCache(BaseCaching):
10+
"""
11+
Overrides put() nad self()
12+
from parent
13+
"""
14+
15+
def __init__(self):
16+
"""initialize"""
17+
super().__init__()
18+
self.queue = deque([])
19+
20+
def put(self, key, item):
21+
"""Add an item in the cache
22+
"""
23+
if key and item:
24+
if len(self.cache_data) == BaseCaching.MAX_ITEMS\
25+
and key not in self.queue:
26+
del_key = self.queue.popleft()
27+
del self.cache_data[del_key]
28+
print("DISCARD: {}".format(del_key))
29+
self.cache_data[key] = item
30+
self.queue.append(key)
31+
32+
def get(self, key):
33+
"""Get an item by key
34+
"""
35+
value = self.cache_data.get(key)
36+
return value

0x01-caching/100-lfu_cache.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/python3
2+
""" 4. MRU Caching
3+
"""
4+
from datetime import datetime
5+
from collections import defaultdict
6+
BaseCaching = __import__('base_caching').BaseCaching
7+
8+
9+
class LFUCache(BaseCaching):
10+
""" BaseCache defines:
11+
- overwrite functions 'put' and 'get' for implement
12+
MRU caching system
13+
"""
14+
def __init__(self):
15+
""" Initiliaze
16+
"""
17+
super().__init__()
18+
self.cache_by_time = {}
19+
self.cache_by_frequency_use = defaultdict(int) # >>> Default value: 0
20+
21+
def put(self, key, item):
22+
"""
23+
Assign to the dictionary self.cache_data the item
24+
value for the key key
25+
If the number of items in self.cache_data is higher
26+
that BaseCaching.MAX_ITEMS:
27+
- must discard the most recently used item (MRU algorithm)
28+
- must print DISCARD: with the key discarded and following by
29+
a new line
30+
"""
31+
if key and item:
32+
self.cache_by_time[key] = datetime.now()
33+
self.cache_data[key] = item
34+
self.cache_by_frequency_use[key] += 1
35+
36+
if len(self.cache_data) > BaseCaching.MAX_ITEMS:
37+
# Sorted elements by frequency_used
38+
frequency_use_filtered = {}
39+
for k, v in self.cache_by_frequency_use.items():
40+
if k != key:
41+
frequency_use_filtered[k] = v
42+
keys_by_frequency_used = sorted(frequency_use_filtered,
43+
key=frequency_use_filtered.get)
44+
key_to_delete = keys_by_frequency_used[0]
45+
46+
# There are more elements with same frequency used count?
47+
count = frequency_use_filtered[key_to_delete]
48+
posibles_elements_to_discard_dict = {}
49+
for k, v in frequency_use_filtered.items():
50+
if v == count:
51+
posibles_elements_to_discard_dict[k] = v
52+
if len(posibles_elements_to_discard_dict) > 1:
53+
elements_to_discard_by_time = {}
54+
for k, v in self.cache_by_time.items():
55+
if k in posibles_elements_to_discard_dict.keys():
56+
elements_to_discard_by_time[k] = v
57+
58+
elements_by_time = sorted(
59+
elements_to_discard_by_time,
60+
key=elements_to_discard_by_time.get)
61+
key_to_delete = elements_by_time[0]
62+
63+
# Delete element with least_frequency_used
64+
del self.cache_by_time[key_to_delete]
65+
del self.cache_data[key_to_delete]
66+
del self.cache_by_frequency_use[key_to_delete]
67+
print('DISCARD: {}'.format(key_to_delete))
68+
69+
def get(self, key):
70+
"""
71+
Return the value in self.cache_data linked to key
72+
"""
73+
element = self.cache_data.get(key)
74+
if element:
75+
self.cache_by_time[key] = datetime.now()
76+
self.cache_by_frequency_use[key] += 1
77+
return element

0x01-caching/2-lifo_cache.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/python3
2+
"""
3+
Module 2-lifo_cache
4+
"""
5+
from base_caching import BaseCaching
6+
7+
8+
class LIFOCache(BaseCaching):
9+
"""
10+
Overrides put() nad self()
11+
from parent
12+
"""
13+
14+
def __init__(self):
15+
"""initialize"""
16+
super().__init__()
17+
self.stack = []
18+
19+
def put(self, key, item):
20+
"""Add an item in the cache
21+
"""
22+
if key and item:
23+
if len(self.cache_data) == BaseCaching.MAX_ITEMS\
24+
and key not in self.stack:
25+
del_key = self.stack.pop()
26+
del self.cache_data[del_key]
27+
print("DISCARD: {}".format(del_key))
28+
self.cache_data[key] = item
29+
self.stack.append(key)
30+
31+
def get(self, key):
32+
"""Get an item by key
33+
"""
34+
value = self.cache_data.get(key)
35+
return value

0x01-caching/3-lru_cache.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/python3
2+
"""
3+
Module 3-lru_cache.py
4+
"""
5+
from base_caching import BaseCaching
6+
7+
8+
class LRUCache(BaseCaching):
9+
"""
10+
Overrides put() nad self()
11+
from parent
12+
"""
13+
14+
def __init__(self):
15+
"""initialize"""
16+
super().__init__()
17+
self.keys = []
18+
19+
def put(self, key, item):
20+
"""Add an item in the cache
21+
"""
22+
if key and item:
23+
if len(self.cache_data) == BaseCaching.MAX_ITEMS\
24+
and key not in self.keys:
25+
del_key = self.keys.pop(0)
26+
del self.cache_data[del_key]
27+
print("DISCARD: {}".format(del_key))
28+
if key in self.keys:
29+
self.keys.remove(key)
30+
self.cache_data[key] = item
31+
self.keys.append(key)
32+
33+
def get(self, key):
34+
"""Get an item by key
35+
"""
36+
if key in self.keys:
37+
self.keys.remove(key)
38+
self.keys.append(key)
39+
value = self.cache_data.get(key)
40+
return value

0x01-caching/4-mru_cache.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/python3
2+
"""
3+
Module 4-mru_cache.py
4+
"""
5+
from base_caching import BaseCaching
6+
7+
8+
class MRUCache(BaseCaching):
9+
"""
10+
Overrides put() nad self()
11+
from parent
12+
"""
13+
14+
def __init__(self):
15+
"""initialize"""
16+
super().__init__()
17+
self.keys = []
18+
19+
def put(self, key, item):
20+
"""Add an item in the cache
21+
"""
22+
if key and item:
23+
if len(self.cache_data) == BaseCaching.MAX_ITEMS\
24+
and key not in self.keys:
25+
del_key = self.keys.pop()
26+
del self.cache_data[del_key]
27+
print("DISCARD: {}".format(del_key))
28+
if key in self.keys:
29+
self.keys.remove(key)
30+
self.cache_data[key] = item
31+
self.keys.append(key)
32+
33+
def get(self, key):
34+
"""Get an item by key
35+
"""
36+
if key in self.keys:
37+
self.keys.remove(key)
38+
self.keys.append(key)
39+
value = self.cache_data.get(key)
40+
return value

0x01-caching/README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
caching
1+
## 0x01. Caching
2+
3+
## Goals
4+
- What a caching system is
5+
- What FIFO means
6+
- What LIFO means
7+
- What LRU means
8+
- What MRU means
9+
- What LFU means
10+
- What the purpose of a caching system
11+
- What limits a caching system have

0x01-caching/base_caching.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/python3
2+
""" BaseCaching module
3+
"""
4+
5+
6+
class BaseCaching():
7+
"""BaseCaching defines:
8+
- constants of your caching system
9+
- where your data are stored (in a dictionary)
10+
"""
11+
MAX_ITEMS = 4
12+
13+
def __init__(self):
14+
"""Initiliaze
15+
"""
16+
self.cache_data = {}
17+
18+
def print_cache(self):
19+
"""Print the cache
20+
"""
21+
print("Current cache:")
22+
for key in sorted(self.cache_data.keys()):
23+
print("{}: {}".format(key, self.cache_data.get(key)))
24+
25+
def put(self, key, item):
26+
"""Add an item in the cache
27+
"""
28+
raise NotImplementedError("\
29+
put must be implemented in your cache class")
30+
31+
def get(self, key):
32+
"""Get an item by key
33+
"""
34+
raise NotImplementedError("\
35+
get must be implemented in your cache class")

0 commit comments

Comments
 (0)