-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathp16_25.py
102 lines (79 loc) · 2.74 KB
/
p16_25.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
class LRUCache:
def __init__(self, max_size):
super().__init__()
self.latest = None
self.oldest = None
self.max_size = max_size
self._dict = {}
def add(self, key, val) -> None:
if key in self._dict:
self._dict[key].val = val
self._bump_node(self._dict[key])
elif len(self._dict) == self.max_size:
self.evict_lru()
new_node = CacheNode(key, val)
if self.latest:
self.latest.right = new_node
else:
self.oldest = new_node
new_node.left = self.latest
self._dict[key] = new_node
self.latest = new_node
# print(f"Self.latest now is {self.latest}, to it's left {self.latest.left}")
def get(self, key):
if key not in self._dict:
raise Exception(f"Key {key} not in cache")
val = self._dict[key].val
self._bump_node(self._dict[key])
return val
def evict_lru(self):
if not self.oldest:
raise Exception("Cannot evict, cache should be empty")
oldest_nodes = self.oldest
# print(f"[Evicting] oldest, which is {oldest_nodes}, on it's right {oldest_nodes.right}")
if oldest_nodes.right:
# print(f"[Evicting] On right is {oldest_nodes.right}")
self.oldest = oldest_nodes.right
oldest_nodes.right.left = None
else:
self.oldest = None
self.latest = None
del self._dict[oldest_nodes.key]
def _bump_node(self, node):
# print(f"Bumping node {node}, w/ LEFT: {node.left} and RIGHT {node.right}")
# print(f"Bumping node in dict: {self._dict[node.left.key] if node.left else 'Nevermind'}")
if node != self.latest:
if node.left:
node.left.right = node.right
else: # You are the oldest
self.oldest = node.right
# Add to the latest nodes, become latest
self.latest.right = node
node.left = self.latest
self.latest = node
def __str__(self):
return f"LRUCache w/ items: {list(self._dict.items())}, oldest: {self.oldest} , newest: {self.latest}"
class CacheNode:
def __init__(self, key, val):
self.key = key
self.val = val
self.right = None
self.left = None
def __str__(self):
return f"CN(k:{self.key}, v:{self.val})"
def __repr__(self):
return self.__str__()
if __name__ == "__main__":
lrc = LRUCache(4)
for i in range(10):
lrc.add(i, i)
assert lrc.get(i) == i
print(lrc)
print("-"*50)
lrc.get(6)
lrc.get(8)
print(lrc)
print("-"*50)
for i in range(10, 16):
lrc.add(i, i)
print(lrc)