Skip to content

Conversation

@BrianLusina
Copy link
Owner

@BrianLusina BrianLusina commented Jan 26, 2026

Describe your change:

LRU Cache implementation

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Documentation change?

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
  • If this pull request resolves one or more open issues then the commit message contains Fixes: #{$ISSUE_NO}.

Summary by CodeRabbit

  • Documentation

    • Added comprehensive LFU Cache documentation covering capacity, get/put behavior, eviction policy, and usage counters
    • Improved LRU Cache documentation with formatting fixes, typo corrections, and structural cleanup
  • Refactor

    • Modernized internal LRU implementation to simplify node handling, improve type clarity, and streamline eviction logic
  • Chores

    • Cleaned up file endings and minor formatting issues

✏️ Tip: You can customize this high-level summary in your review settings.

@BrianLusina BrianLusina self-assigned this Jan 26, 2026
@BrianLusina BrianLusina added enhancement Algorithm Algorithm Problem Datastructures Datastructures Documentation Documentation Updates Hash Map Hash Map Data structure LinkedList Linked List Data Structure DoublyLinkedList Doubly Linked List Design labels Jan 26, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Added LFU cache README; reformatted and corrected LRU README; refactored LRU implementation to use sentinel DoubleNode-based doubly linked list, added/expanded type annotations, and changed get/put signatures and internal field names.

Changes

Cohort / File(s) Summary
Documentation
datastructures/lfucache/README.md, datastructures/lrucache/README.md
Added LFU README content describing LFUCache behavior. Rewrote LRU README header/formatting, fixed typo ("cahing" → "caching"), and ensured trailing newline.
LRU Cache Implementation
datastructures/lrucache/with_internal_linked_list.py
Replaced Node-based list with sentinel DoubleNode head/tail; updated lookups to Dict[str | int, DoubleNode]; get(key: str | int) now returns Optional[Any]; helper signatures accept DoubleNode; changed prevprevious and eviction references to tail.previous. Boundary/null checks removed in favor of sentinels.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through docs and doubled my nodes,
Sentinel head and tail on tidy roads.
Keys of string or int, snug in a row,
Optional returns where smart caches grow. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor(datastructures, lru-cache): refactor lru cache' is partially related to the changeset. It correctly identifies the refactoring of the LRU cache, but it is somewhat generic and redundant ('refactor' appears twice), and does not highlight the specific technical changes like the DoubleNode implementation or type annotation improvements.
Description check ✅ Passed The PR description follows the required template with all sections present and properly filled out. The author marked appropriate checklist items and only left unchecked the issue-resolution item, which may not apply to this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
datastructures/lfucache/README.md (1)

14-14: Typo: missing "t" in "the".

"he least recently used" should be "the least recently used".

📝 Suggested fix
-he least recently used key would be invalidated.
+the least recently used key would be invalidated.
🤖 Fix all issues with AI agents
In `@datastructures/lrucache/README.md`:
- Line 6: Fix the typo in the README by changing "cahing" to "caching" in the
datastructures/lrucache/README.md line that currently reads "We are cahing the
results of web queries" so the sentence correctly reads "We are caching the
results of web queries".

In `@datastructures/lrucache/with_internal_linked_list.py`:
- Around line 11-14: The constructor sets up sentinel nodes using DoubleNode but
incorrectly assigns self.tail.prev instead of the DoubleNode attribute name
previous; update the initialization to use self.head.next = self.tail and
self.tail.previous = self.head (and ensure any other uses of prev are changed to
previous) so the linked-list sentinel wiring matches the DoubleNode API (inspect
DoubleNode, head, tail, and any methods relying on previous).

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions bot force-pushed the feat/datastructures-lru-cache branch from bd733b2 to 991c2a7 Compare January 26, 2026 17:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@datastructures/lrucache/with_internal_linked_list.py`:
- Around line 5-14: The constructor (__init__) doesn't guard against capacity <=
0 which allows put() to trigger eviction of sentinel nodes (tail.previous) and
crash; update the __init__ (the constructor that sets self.capacity,
self.lookup, self.head, self.tail and uses DoubleNode) to validate capacity
(e.g., raise ValueError for capacity < 1 or coerce to a minimum of 1) so
negative or zero capacities are rejected before any put()/eviction logic touches
head/tail/lookup.
🧹 Nitpick comments (1)
datastructures/lrucache/with_internal_linked_list.py (1)

36-51: Align put() value type with get() return type.

get() returns Optional[Any], but put() restricts value to int. If the cache is intended to be generic (as suggested by Optional[Any] and DoubleNode.data: Any), consider widening the type.

♻️ Suggested tweak
-def put(self, key: str | int, value: int) -> None:
+def put(self, key: str | int, value: Any) -> None:

Comment on lines 5 to +14
def __init__(self, capacity: int):
self.capacity = capacity
self.lookup = {}
self.lookup: Dict[str | int, DoubleNode] = {}
self.size = 0
self.head = Node()
self.tail = Node()
# Using sentinel head and tail nodes avoids null checks when adding/removing nodes at boundaries. This means
# every real node always has non-null prev/next pointers, simplifying insertion and deletion logic dramatically
self.head = DoubleNode(0)
self.tail = DoubleNode(0)
self.head.next = self.tail
self.tail.prev = self.head
self.tail.previous = self.head
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard against zero/negative capacity to avoid sentinel eviction.

With capacity <= 0, put() falls into eviction logic and attempts to delete the sentinel (tail.previous), which can raise KeyError/AttributeError. A simple validation in __init__ avoids this class of bugs.

🛠️ Suggested fix
 def __init__(self, capacity: int):
+    if capacity <= 0:
+        raise ValueError("capacity must be a positive integer")
     self.capacity = capacity
     self.lookup: Dict[str | int, DoubleNode] = {}
     self.size = 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def __init__(self, capacity: int):
self.capacity = capacity
self.lookup = {}
self.lookup: Dict[str | int, DoubleNode] = {}
self.size = 0
self.head = Node()
self.tail = Node()
# Using sentinel head and tail nodes avoids null checks when adding/removing nodes at boundaries. This means
# every real node always has non-null prev/next pointers, simplifying insertion and deletion logic dramatically
self.head = DoubleNode(0)
self.tail = DoubleNode(0)
self.head.next = self.tail
self.tail.prev = self.head
self.tail.previous = self.head
def __init__(self, capacity: int):
if capacity <= 0:
raise ValueError("capacity must be a positive integer")
self.capacity = capacity
self.lookup: Dict[str | int, DoubleNode] = {}
self.size = 0
# Using sentinel head and tail nodes avoids null checks when adding/removing nodes at boundaries. This means
# every real node always has non-null prev/next pointers, simplifying insertion and deletion logic dramatically
self.head = DoubleNode(0)
self.tail = DoubleNode(0)
self.head.next = self.tail
self.tail.previous = self.head
🤖 Prompt for AI Agents
In `@datastructures/lrucache/with_internal_linked_list.py` around lines 5 - 14,
The constructor (__init__) doesn't guard against capacity <= 0 which allows
put() to trigger eviction of sentinel nodes (tail.previous) and crash; update
the __init__ (the constructor that sets self.capacity, self.lookup, self.head,
self.tail and uses DoubleNode) to validate capacity (e.g., raise ValueError for
capacity < 1 or coerce to a minimum of 1) so negative or zero capacities are
rejected before any put()/eviction logic touches head/tail/lookup.

@BrianLusina BrianLusina merged commit 1acda91 into main Jan 26, 2026
6 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Algorithm Algorithm Problem Datastructures Datastructures Design Documentation Documentation Updates DoublyLinkedList Doubly Linked List enhancement Hash Map Hash Map Data structure LinkedList Linked List Data Structure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants