Skip to content

Commit a0ee21d

Browse files
feat(priority-expiry-cache): cache coding challenge
1 parent f44324b commit a0ee21d

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import time
2+
3+
4+
class LinkedListNode:
5+
def __init__(self, key):
6+
# Key: the key inserted into the cache
7+
self.key = key
8+
self.next = None
9+
self.prev = None
10+
11+
12+
class LinkedList:
13+
def __init__(self):
14+
self.head = LinkedListNode(-1)
15+
self.tail = LinkedListNode(-1)
16+
17+
self.head.next = self.tail
18+
self.tail.prev = self.head
19+
20+
21+
class BinarySearchTree:
22+
def __init__(self):
23+
self.root = None
24+
25+
# Gets the earliest expiry time or lowest priority
26+
def getMinValueNode(self):
27+
current = self.root
28+
29+
# loop down to find the leftmost leaf
30+
while current and current.left:
31+
current = current.left
32+
33+
return current
34+
35+
36+
class ExpireTimeNode:
37+
def __init__(self, time, keys=set()):
38+
# ExpireTime of the entry
39+
self.time = time
40+
# Set of keys with the expireTime
41+
self.keys = keys
42+
self.left = None
43+
self.right = None
44+
45+
def removeKeyInNode(self):
46+
# removes arbitrary key from the list of keys
47+
key = self.keys.pop()
48+
if not self.keys:
49+
self.deleteNode()
50+
return key
51+
52+
def deleteKeyInNode(self, key):
53+
self.keys.remove(key)
54+
if not self.keys:
55+
self.deleteNode()
56+
57+
def deleteNode(self):
58+
# Removes the Node from the BST
59+
pass
60+
61+
62+
class PriorityNode:
63+
def __init__(self, priority, lru={}):
64+
# Priority of the entry
65+
self.priority = priority
66+
# LRU Linked List Map: key is the key interested into the cache, value is a LinkedListNode
67+
self.lru = lru
68+
# Linked List: linked list to keep track of the head and tail of the lru linked list
69+
self.linkedList = LinkedList()
70+
self.left = None
71+
self.right = None
72+
73+
def deleteKeyInNode(self, key):
74+
llNode = self.lru[key]
75+
llNode.prev.next = llNode.next
76+
llNode.next.prev = llNode.prev
77+
del self.lru[key]
78+
if not self.lru:
79+
self.deleteNode()
80+
81+
def deleteNode(self):
82+
# Removes the Node from the BST
83+
pass
84+
85+
86+
class PriorityExpiryCache:
87+
def __init__(self, maxItems):
88+
self.maxItems = maxItems
89+
# Cache (map): key is the key inserted into the cache, value is an object with the value, priority and expireTime
90+
self.cache = {}
91+
# Expire Time BST: ordered based on the expire time
92+
self.expireTimeTree = BinarySearchTree()
93+
# Priority BST: ordered based on the priority
94+
self.priorityTree = BinarySearchTree()
95+
96+
def evictItem(self):
97+
keyToDelete = None
98+
earliestExpiryTimeNode = self.expireTimeTree.getMinValueNode()
99+
if earliestExpiryTimeNode.key < int(time.time()):
100+
keyToDelete = earliestExpiryTimeNode.removeKeyInNode()
101+
102+
keyPriority = self.cache[keyToDelete].priority
103+
104+
priorityNode = self.priorityTree.getKeyNode(keyPriority)
105+
priorityNode.deleteKeyInNode(keyToDelete)
106+
else:
107+
lowestPriorityNode = self.priorityTree.getMinValueNode()
108+
keyToDelete = lowestPriorityNode.linkedList.tail.key
109+
priorityNode.deleteKeyInNode(keyToDelete)
110+
111+
keyExpireTime = self.cache[keyToDelete].expireTime
112+
113+
expireTimeNode = self.expireTimeTree.getKeyNode(keyExpireTime)
114+
expireTimeNode.deleteKeyInNode(keyToDelete)
115+
116+
del self.cache[keyToDelete]
117+
118+
def evictItems(self):
119+
while len(self.cache.keys()) > self.maxItems:
120+
self.evictItem()

0 commit comments

Comments
 (0)