From 18d6099b79d6dc9032afa8957a54f700132d2503 Mon Sep 17 00:00:00 2001 From: Abubakar-Meigag <113248042+Abubakar-Meigag@users.noreply.github.com> Date: Tue, 30 Jun 2026 18:05:36 +0100 Subject: [PATCH 1/2] London | 26-SDC-Mar | beko | Sprint 2 | implement an LRU cache in python --- Sprint-2/implement_lru_cache/lru_cache.py | 61 +++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/Sprint-2/implement_lru_cache/lru_cache.py b/Sprint-2/implement_lru_cache/lru_cache.py index e69de29..f567fe4 100644 --- a/Sprint-2/implement_lru_cache/lru_cache.py +++ b/Sprint-2/implement_lru_cache/lru_cache.py @@ -0,0 +1,61 @@ +from typing import Optional + +class _Node: + def __init__(self, key=None, value=None): + self.key = key + self.value = value + self.prev: Optional["_Node"] = None + self.next: Optional["_Node"] = None + +class LruCache: + def __init__(self, limit): + if limit <= 0: + raise ValueError("limit must be positive") + + self.limit = limit + self.cache = {} + + self.head = _Node() + self.tail = _Node() + self.head.next = self.tail + self.tail.prev = self.head + + def remove(self, node): + node.prev.next = node.next + node.next.prev = node.prev + + def add_to_front(self, node): + next_node = self.head.next + assert next_node is not None + + node.next = next_node + node.prev = self.head + next_node.prev = node + self.head.next = node + + def get(self, key): + if key not in self.cache: + return None + + node = self.cache[key] + self.remove(node) + self.add_to_front(node) + return node.value + + def set(self, key, value): + if key in self.cache: + node = self.cache[key] + node.value = value + self.remove(node) + self.add_to_front(node) + return + + node = _Node(key, value) + self.cache[key] = node + self.add_to_front(node) + + if len(self.cache) > self.limit: + lru = self.tail.prev + assert lru is not None + self.remove(lru) + del self.cache[lru.key] From a80a8938ee419e58ddb25ded41f9897e4e74fe2f Mon Sep 17 00:00:00 2001 From: Abubakar-Meigag <113248042+Abubakar-Meigag@users.noreply.github.com> Date: Wed, 1 Jul 2026 22:38:03 +0100 Subject: [PATCH 2/2] update following SRP implementation --- Sprint-2/implement_lru_cache/lru_cache.py | 56 ++++++++++++++--------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/Sprint-2/implement_lru_cache/lru_cache.py b/Sprint-2/implement_lru_cache/lru_cache.py index f567fe4..a17da7e 100644 --- a/Sprint-2/implement_lru_cache/lru_cache.py +++ b/Sprint-2/implement_lru_cache/lru_cache.py @@ -1,61 +1,73 @@ from typing import Optional class _Node: + def __init__(self, key=None, value=None): - self.key = key + self.key = key self.value = value self.prev: Optional["_Node"] = None self.next: Optional["_Node"] = None - -class LruCache: - def __init__(self, limit): - if limit <= 0: - raise ValueError("limit must be positive") - - self.limit = limit - self.cache = {} - + +class DoublyLinkedList: + + def __init__(self): self.head = _Node() self.tail = _Node() self.head.next = self.tail self.tail.prev = self.head - def remove(self, node): + def remove(self, node: _Node): + assert node.prev is not None + assert node.next is not None node.prev.next = node.next node.next.prev = node.prev - def add_to_front(self, node): + def add_to_front(self, node: _Node): next_node = self.head.next assert next_node is not None - node.next = next_node node.prev = self.head next_node.prev = node self.head.next = node + def remove_last(self) -> _Node: + lru = self.tail.prev + assert lru is not None + self.remove(lru) + return lru + + +class LruCache: + + def __init__(self, limit): + if limit <= 0: + raise ValueError("limit must be positive") + + self.limit = limit + self.cache = {} + self.list = DoublyLinkedList() + def get(self, key): if key not in self.cache: return None - + node = self.cache[key] - self.remove(node) - self.add_to_front(node) + self.list.remove(node) + self.list.add_to_front(node) return node.value def set(self, key, value): if key in self.cache: node = self.cache[key] node.value = value - self.remove(node) - self.add_to_front(node) + self.list.remove(node) + self.list.add_to_front(node) return node = _Node(key, value) self.cache[key] = node - self.add_to_front(node) + self.list.add_to_front(node) if len(self.cache) > self.limit: - lru = self.tail.prev - assert lru is not None - self.remove(lru) + lru = self.list.remove_last() del self.cache[lru.key]