From 024cc9adcd7773efd64c18a5bd2a93963837d713 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 19 Aug 2024 14:09:18 -0400 Subject: [PATCH 1/4] wip --- 1-lru-cache/python/src/cache.py | 81 ++++++++++++++++++++++--------- 1-lru-cache/python/tests/cache.py | 7 +++ 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/1-lru-cache/python/src/cache.py b/1-lru-cache/python/src/cache.py index 549aefa..b8fbd5b 100644 --- a/1-lru-cache/python/src/cache.py +++ b/1-lru-cache/python/src/cache.py @@ -8,6 +8,35 @@ def __init__(self, maxSize) -> None: self.maxSize = maxSize self.lookupTable = {} + def move_to_tail(self, key): + node = self.lookupTable[key] + # Remove node from current place + if node == self.tail: + return + + if node == self.head: + self.head = node.nextNode + self.prevNode = None + else: + left = node.prevNode + right = node.nextNode + left.nextNode = right + right.prevNode = left + + # add node at tail + before_tail = self.tail.prevNode + before_tail.nextNode = node + node.prevNode = before_tail + node.nextNode = None + self.tail = node + + def remove_from_head(self, key): + # Note: copied from above + self.head = node.nextNode + self.prevNode = None + # This part is only difference from above + del self.lookupTable[key] + def get(self, key) -> int: if None == key: return None @@ -19,36 +48,44 @@ def get(self, key) -> int: if self.tail is result: return result.value - if None == result.prevNode: - self.head = result.nextNode - self.head.prevNode = None + self.move_to_tail() - self.tail.nextNode = result - result.nextNode = None - result.prevNode = None - self.tail = result - return result.value + # if None == result.prevNode: + # self.head = result.nextNode + # self.head.prevNode = None + + # self.tail.nextNode = result + # result.nextNode = None + # result.prevNode = None + # self.tail = result + # return result.value def put(self, key, val) -> None: if None == key: return None - self.currentSize += 1 - if self.currentSize > self.maxSize: - self.lookupTable.pop(self.head.key) - self.head = self.head.nextNode - self.head.prevNode = None - self.currentSize -= 1 - - newNode = Node(key, val, self.tail, None) - if None == self.tail: - self.head = newNode + self.move_to_tail(val) + if self.currentSize >= self.maxSize: + self.remove_from_head() else: - self.tail.nextNode = newNode + self.currentSize += 1 + + # self.currentSize += 1 + # if self.currentSize > self.maxSize: + # self.lookupTable.pop(self.head.key) + # self.head = self.head.nextNode + # self.head.prevNode = None + # self.currentSize -= 1 - self.tail = newNode - self.lookupTable[key] = newNode - + # newNode = Node(key, val, self.tail, None) + # if None == self.tail: + # self.head = newNode + # else: + # self.tail.nextNode = newNode + + # self.tail = newNode + # self.lookupTable[key] = newNode + def toArray(self): a = [] current = self.head diff --git a/1-lru-cache/python/tests/cache.py b/1-lru-cache/python/tests/cache.py index 51a0713..eec4800 100644 --- a/1-lru-cache/python/tests/cache.py +++ b/1-lru-cache/python/tests/cache.py @@ -1,6 +1,13 @@ from src.cache import Cache import unittest +""" +most recent is at tail + +we kick items at the head when at capacity +""" + + class CachTest(unittest.TestCase): def test_constructs(self): From f34447146a996805444fa9a8eea5d2228fd52c4f Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 19 Aug 2024 14:18:00 -0400 Subject: [PATCH 2/4] only 2 failing tests remaining --- 1-lru-cache/python/src/cache.py | 29 ++++++++++++++++++++--------- 1-lru-cache/python/src/node.py | 4 +++- 1-lru-cache/python/tests/cache.py | 4 ++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/1-lru-cache/python/src/cache.py b/1-lru-cache/python/src/cache.py index b8fbd5b..e3620e4 100644 --- a/1-lru-cache/python/src/cache.py +++ b/1-lru-cache/python/src/cache.py @@ -16,7 +16,7 @@ def move_to_tail(self, key): if node == self.head: self.head = node.nextNode - self.prevNode = None + node.prevNode = None else: left = node.prevNode right = node.nextNode @@ -25,13 +25,15 @@ def move_to_tail(self, key): # add node at tail before_tail = self.tail.prevNode - before_tail.nextNode = node - node.prevNode = before_tail + tail = self.tail + tail.nextNode = node + node.prevNode = tail node.nextNode = None self.tail = node def remove_from_head(self, key): # Note: copied from above + node = self.lookupTable[key] self.head = node.nextNode self.prevNode = None # This part is only difference from above @@ -48,7 +50,7 @@ def get(self, key) -> int: if self.tail is result: return result.value - self.move_to_tail() + self.move_to_tail(key) # if None == result.prevNode: # self.head = result.nextNode @@ -63,12 +65,21 @@ def get(self, key) -> int: def put(self, key, val) -> None: if None == key: return None - - self.move_to_tail(val) - if self.currentSize >= self.maxSize: - self.remove_from_head() + + newNode = Node(key, val, self.tail, None) + if None == self.tail: + self.head = newNode else: - self.currentSize += 1 + self.tail.nextNode = newNode + + self.tail = newNode + self.lookupTable[key] = newNode + + self.move_to_tail(key) + self.currentSize += 1 + if self.currentSize > self.maxSize: + self.remove_from_head(key) + self.currentSize -= 1 # self.currentSize += 1 # if self.currentSize > self.maxSize: diff --git a/1-lru-cache/python/src/node.py b/1-lru-cache/python/src/node.py index ab8129c..63a0759 100644 --- a/1-lru-cache/python/src/node.py +++ b/1-lru-cache/python/src/node.py @@ -4,4 +4,6 @@ def __init__(self, key, value, prevNode, nextNode) -> None: self.value = value self.prevNode = prevNode self.nextNode = nextNode - \ No newline at end of file + + def __repr__(self): + return f"Node({self.key=},{self.value=})" diff --git a/1-lru-cache/python/tests/cache.py b/1-lru-cache/python/tests/cache.py index eec4800..4cedf1c 100644 --- a/1-lru-cache/python/tests/cache.py +++ b/1-lru-cache/python/tests/cache.py @@ -57,9 +57,13 @@ def test_gets_tail(self): def test_gets_head(self): cache = Cache(3) cache.put('bananas', 111) + print(cache.toArray()) cache.put('apples', 222) + print(cache.toArray()) cache.put('oranges', 333) + print(cache.toArray()) cache.get('bananas') + print(cache.toArray()) self.assertEqual(cache.toArray(), [222, 333, 111]) def test_moves_tail_when_getting_middle(self): From 17111758c364664edb1dc446a762c9ecde463a6f Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 19 Aug 2024 14:23:04 -0400 Subject: [PATCH 3/4] all tests pass --- 1-lru-cache/python/src/cache.py | 13 ++++++++----- 1-lru-cache/python/tests/cache.py | 6 +----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/1-lru-cache/python/src/cache.py b/1-lru-cache/python/src/cache.py index e3620e4..5b782a5 100644 --- a/1-lru-cache/python/src/cache.py +++ b/1-lru-cache/python/src/cache.py @@ -31,11 +31,14 @@ def move_to_tail(self, key): node.nextNode = None self.tail = node - def remove_from_head(self, key): + def remove_from_head(self): # Note: copied from above - node = self.lookupTable[key] - self.head = node.nextNode - self.prevNode = None + key = self.head.key + + right = self.head.nextNode + self.head = right + right.prevNode = None + # This part is only difference from above del self.lookupTable[key] @@ -78,7 +81,7 @@ def put(self, key, val) -> None: self.move_to_tail(key) self.currentSize += 1 if self.currentSize > self.maxSize: - self.remove_from_head(key) + self.remove_from_head() self.currentSize -= 1 # self.currentSize += 1 diff --git a/1-lru-cache/python/tests/cache.py b/1-lru-cache/python/tests/cache.py index 4cedf1c..4d8da9f 100644 --- a/1-lru-cache/python/tests/cache.py +++ b/1-lru-cache/python/tests/cache.py @@ -42,7 +42,7 @@ def test_enforces_max_size_on_set(self): cache.put('bananas', 111) cache.put('apples', 222) cache.put('oranges', 333) - cache.put('cucumbers', 444) + cache.put('cucumbers', 444) self.assertEqual(cache.currentSize, 3) self.assertEqual(cache.toArray(), [222, 333, 444]) @@ -57,13 +57,9 @@ def test_gets_tail(self): def test_gets_head(self): cache = Cache(3) cache.put('bananas', 111) - print(cache.toArray()) cache.put('apples', 222) - print(cache.toArray()) cache.put('oranges', 333) - print(cache.toArray()) cache.get('bananas') - print(cache.toArray()) self.assertEqual(cache.toArray(), [222, 333, 111]) def test_moves_tail_when_getting_middle(self): From 828fb32981cad4a9e91e3bd29b248112671a39a6 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Mon, 19 Aug 2024 14:23:31 -0400 Subject: [PATCH 4/4] cleanup --- 1-lru-cache/python/src/cache.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/1-lru-cache/python/src/cache.py b/1-lru-cache/python/src/cache.py index 5b782a5..ec6d7cc 100644 --- a/1-lru-cache/python/src/cache.py +++ b/1-lru-cache/python/src/cache.py @@ -55,16 +55,6 @@ def get(self, key) -> int: self.move_to_tail(key) - # if None == result.prevNode: - # self.head = result.nextNode - # self.head.prevNode = None - - # self.tail.nextNode = result - # result.nextNode = None - # result.prevNode = None - # self.tail = result - # return result.value - def put(self, key, val) -> None: if None == key: return None @@ -84,22 +74,6 @@ def put(self, key, val) -> None: self.remove_from_head() self.currentSize -= 1 - # self.currentSize += 1 - # if self.currentSize > self.maxSize: - # self.lookupTable.pop(self.head.key) - # self.head = self.head.nextNode - # self.head.prevNode = None - # self.currentSize -= 1 - - # newNode = Node(key, val, self.tail, None) - # if None == self.tail: - # self.head = newNode - # else: - # self.tail.nextNode = newNode - - # self.tail = newNode - # self.lookupTable[key] = newNode - def toArray(self): a = [] current = self.head