Skip to content

Conversation

@BrianLusina
Copy link
Owner

@BrianLusina BrianLusina commented Jan 7, 2026

Describe your change:

  • Reconstruct Itinerary
  • 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

  • New Features

    • Added Reconstruct Itinerary and Cat and Mouse graph algorithms; added Reorder List under linked-list algorithms.
  • Documentation

    • Added comprehensive guides for Reconstruct Itinerary and Cat and Mouse with problem statements, solution approaches, examples, and complexity notes.
  • Tests

    • Added test suites validating the new graph algorithms.
  • Chores

    • Relocated the linked-list Reorder List test entry to the new Reorder List path.

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

@BrianLusina BrianLusina self-assigned this Jan 7, 2026
@BrianLusina BrianLusina added enhancement Algorithm Algorithm Problem Datastructures Datastructures Documentation Documentation Updates Graph Graph data structures and algorithms Array Array data structure Depth First Search labels Jan 7, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

Warning

Rate limit exceeded

@BrianLusina has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 303bcb7 and 5e0f104.

📒 Files selected for processing (3)
  • algorithms/graphs/cat_and_mouse/__init__.py
  • algorithms/graphs/reconstruct_itinerary/README.md
  • algorithms/graphs/reconstruct_itinerary/__init__.py
📝 Walkthrough

Walkthrough

Adds two graph algorithm features (Reconstruct Itinerary and Cat and Mouse) with implementations, READMEs, and tests; updates DIRECTORY.md to register Reconstruct Itinerary and relocates a Reorder List test entry.

Changes

Cohort / File(s) Summary
Manifest / Index
DIRECTORY.md
Added Reconstruct Itinerary under Graphs; moved Reorder List test entry from Tests -> Datastructures -> Linked List to Datastructures -> Linked Lists.
Reconstruct Itinerary — Docs
algorithms/graphs/reconstruct_itinerary/README.md
New README describing problem, constraints, examples, Hierholzer-based solution overview, algorithm steps, and complexity notes.
Reconstruct Itinerary — Implementation
algorithms/graphs/reconstruct_itinerary/__init__.py
Added find_itinerary(tickets) (iterative stack approach) and find_itinerary_using_hierholzers(tickets) (recursive Hierholzer DFS). Note: adjacency lists are sorted in reverse and results are reversed before return.
Reconstruct Itinerary — Tests
algorithms/graphs/reconstruct_itinerary/test_reconstruct_itinerary.py
New parameterized tests RECONSTRUCT_ITINERARY_TEST_CASES validating both implementations across example cases.
Cat and Mouse — Docs
algorithms/graphs/cat_and_mouse/README.md
New README documenting the Cat and Mouse game, state-space coloring approach, propagation rules, and complexity.
Cat and Mouse — Implementation
algorithms/graphs/cat_and_mouse/__init__.py
Added cat_mouse_game(graph) implementing retrograde percolation via state coloring, predecessor generation, degree tracking, and BFS-style propagation.
Cat and Mouse — Tests
algorithms/graphs/cat_and_mouse/test_cat_and_mouse.py
New parameterized unittest cases validating cat_mouse_game against expected outcomes.

Sequence Diagram(s)

(omitted — changes do not introduce multi-component sequential interactions meeting the diagram criteria)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop through nodes and sorted strings,
Tickets stitched like tiny wings,
I chase a mouse, then map the sky—
Reversed steps, bright paths nearby.
Hooray for tests that make me sing!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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 accurately describes the main change: adding a Reconstruct Itinerary algorithm to the graphs module.
Description check ✅ Passed The description follows the required template with all sections completed, including a clear change description and a comprehensive checklist with appropriate items marked.

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


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

🤖 Fix all issues with AI agents
In @algorithms/graphs/reconstruct_itinerary/__init__.py:
- Line 35: Update the inline comment "After this backtrack to the top airport in
the stack and continue to traaverse it's children" by fixing the typos: change
"traaverse" to "traverse" and "it's" to the possessive "its" so the comment
reads "After this backtrack to the top airport in the stack and continue to
traverse its children".

In @algorithms/graphs/reconstruct_itinerary/README.md:
- Line 34: The README uses the non-hyphenated phrase "Depth First Search";
update that occurrence to the standard hyphenated form "Depth-First Search"
(e.g., modify the line containing "Depth First Search" in the
algorithms/graphs/reconstruct_itinerary/README.md to read "Depth-First Search")
so terminology is consistent.
🧹 Nitpick comments (3)
algorithms/graphs/reconstruct_itinerary/__init__.py (2)

16-27: Consider using defaultdict for graph construction.

The manual dictionary initialization pattern could be simplified using defaultdict(list), which is already imported (though used only in the second function).

♻️ Optional refactor using defaultdict
-    graph = {}
+    graph: DefaultDict[str, List[str]] = defaultdict(list)
     # Create a graph for each airport and keep list of airport reachable from it
     for src, dst in tickets:
-        if src in graph:
-            graph[src].append(dst)
-        else:
-            graph[src] = [dst]
+        graph[src].append(dst)

51-61: Consider adding a docstring for consistency.

The first function has a docstring, but this function lacks one. Adding a docstring would maintain consistency and improve documentation.

📝 Add docstring
 def find_itinerary_using_hierholzers(tickets: List[List[str]]) -> List[str]:
+    """
+    Reconstructs the itinerary from a given list of tickets using Hierholzer's algorithm.
+    Args:
+        tickets (list): list of lists of tickets [departure, arrival]
+    Returns:
+        List[str]: reconstructed itinerary starting from JFK
+    """
     flight_map: DefaultDict[str, List[str]] = defaultdict(list)
algorithms/graphs/reconstruct_itinerary/test_reconstruct_itinerary.py (1)

9-205: Consider adding an edge case test for empty input.

The test cases are comprehensive, covering various scenarios including simple paths, cycles, and complex branching. However, there's no test case for empty input ([]), which is explicitly handled in find_itinerary but not in find_itinerary_using_hierholzers.

🧪 Add empty input test case
 RECONSTRUCT_ITINERARY_TEST_CASES = [
+    ([], []),  # Empty input edge case
     ([["JFK", "EDU"], ["EDU", "LEX"], ["LEX", "MUO"]], ["JFK", "EDU", "LEX", "MUO"]),

Note: This would also reveal that find_itinerary_using_hierholzers returns ["JFK"] for empty input instead of [], which may need to be addressed in the implementation if consistent behavior is desired.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b8a6d4 and c8e3464.

⛔ Files ignored due to path filters (18)
  • algorithms/graphs/reconstruct_itinerary/images/examples/reconstruct_itinerary_example_1.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/examples/reconstruct_itinerary_example_2.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/examples/reconstruct_itinerary_example_3.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_1.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_10.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_11.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_12.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_13.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_14.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_15.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_2.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_3.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_4.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_5.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_6.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_7.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_8.png is excluded by !**/*.png
  • algorithms/graphs/reconstruct_itinerary/images/solutions/reconstruct_itinerary_solution_9.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • DIRECTORY.md
  • algorithms/graphs/reconstruct_itinerary/README.md
  • algorithms/graphs/reconstruct_itinerary/__init__.py
  • algorithms/graphs/reconstruct_itinerary/test_reconstruct_itinerary.py
🧰 Additional context used
🪛 LanguageTool
algorithms/graphs/reconstruct_itinerary/README.md

[grammar] ~34-~34: Use a hyphen to join words.
Context: ...ample_3.png) ## Related Topics - Depth First Search - Graph - Eulerian Circuit ...

(QB_NEW_EN_HYPHEN)


[style] ~78-~78: Using many exclamation marks might seem excessive (in this case: 15 exclamation marks for a text that’s 5949 characters long)
Context: ...s/reconstruct_itinerary_solution_1.png) Solution 2 Solution 3 Solution 4 Solution 5 Solution 6 Solution 7 Solution 8 Solution 9 Solution 10 Solution 11 Solution 12 Solution 13 ![Solution 14](./images/solutions/reconst...

(EN_EXCESSIVE_EXCLAMATION)

🪛 markdownlint-cli2 (0.18.1)
algorithms/graphs/reconstruct_itinerary/README.md

48-48: Blank line inside blockquote

(MD028, no-blanks-blockquote)

DIRECTORY.md

111-111: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


112-112: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


326-326: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


327-327: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)

🔇 Additional comments (11)
DIRECTORY.md (2)

111-112: LGTM!

The new Reconstruct Itinerary entry follows the existing directory structure and indentation conventions. The static analysis hints about indentation are false positives since this file consistently uses 4-space indentation for nested list items throughout.


326-327: LGTM!

The Reorder List entry is correctly placed and follows the established formatting conventions.

algorithms/graphs/reconstruct_itinerary/__init__.py (4)

1-2: LGTM!

The imports are appropriate for the implementation. Using DefaultDict type hint with defaultdict is a good practice for type clarity.


5-14: LGTM!

The function signature with type hints and docstring is well-documented. The early return for empty input is appropriate.


37-48: LGTM!

The stack-based traversal logic correctly implements the post-order pattern for Hierholzer's algorithm. The result reversal at the end produces the correct itinerary order.

Minor style note: while stack: is slightly more Pythonic than while len(stack) > 0:, but this is a negligible preference.


63-80: LGTM!

The recursive DFS implementation correctly applies Hierholzer's algorithm. The post-order accumulation (appending after visiting all destinations) combined with the final reversal produces the correct itinerary. The nested function design is clean and maintains proper encapsulation.

algorithms/graphs/reconstruct_itinerary/README.md (3)

1-16: LGTM!

The problem description is clear and well-documented with examples explaining lexicographical ordering. The constraints and notes are appropriately included.


38-58: LGTM!

The solution explanation clearly describes Hierholzer's algorithm and the approach. The step-by-step breakdown of the algorithm is well-structured and educational.

Note: The static analysis hint about the blank line between blockquotes (line 48) can be safely ignored as the two blockquotes intentionally explain different concepts (Hierholzer's algorithm vs Eulerian path).


94-109: LGTM!

The complexity analysis is thorough, explaining both the DFS traversal cost and the sorting overhead. The distinction between worst-case (star-shaped graph) and average scenarios is helpful.

algorithms/graphs/reconstruct_itinerary/test_reconstruct_itinerary.py (2)

1-7: LGTM!

The imports are appropriate. Using parameterized for test case expansion is a good practice that reduces code duplication.


208-223: LGTM!

The test class structure is clean. Testing both implementations with the same expected outputs ensures behavioral consistency between the iterative and recursive approaches.

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Warnings
⚠️ ❗ Big PR

: Pull Request size seems relatively large. If Pull Request contains multiple changes, split each into separate PR will helps faster, easier review.

Generated by 🚫 dangerJS against 5e0f104

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

🤖 Fix all issues with AI agents
In @algorithms/graphs/cat_and_mouse/__init__.py:
- Line 47: The condition uses identity comparison: replace the object identity
check "color[i2, j2, t2] is draw" with a value equality check using "==" so that
the code compares the value of color at indices i2, j2, t2 to draw; update the
conditional in the relevant function where color, i2, j2, t2, and draw are used
to use "==" instead of "is".

In @DIRECTORY.md:
- Around line 90-91: Fix markdown list indentation for the three sections
flagged by the linter: adjust the "Cat And Mouse" lines so the category header
"Cat And Mouse" is indented by 2 spaces and its entry "[Test Cat And
Mouse](...)" is indented by 4 spaces; do the same for "Reconstruct Itinerary"
(make the header 2 spaces and its test link 4 spaces) and "Reorder List" (header
2 spaces, entry 4 spaces) so they match the repository's consistent list
indentation pattern.
🧹 Nitpick comments (2)
algorithms/graphs/cat_and_mouse/__init__.py (2)

43-43: Consider renaming c to winner for clarity.

The variable c is used for both cat position (in parents function) and the winning color here. Renaming to winner or outcome would improve readability.

♻️ Suggested improvement
-        i, j, t, c = queue.popleft()
+        i, j, t, winner = queue.popleft()
         # for every parent of this node i, j, t :
         for i2, j2, t2 in parents(i, j, t):
             # if this parent is not colored :
             if color[i2, j2, t2] == draw:
                 # if the parent can make a winning move (ie. mouse to MOUSE), do so
-                if t2 == c:  # winning move
-                    color[i2, j2, t2] = c
-                    queue.append((i2, j2, t2, c))
+                if t2 == winner:  # winning move
+                    color[i2, j2, t2] = winner
+                    queue.append((i2, j2, t2, winner))

5-10: Consider adding a docstring with doctests.

Per the project's contribution guidelines, functions should include doctests. A docstring would document the expected behavior and provide inline tests.

📝 Example docstring
def cat_mouse_game(graph: List[List[int]]) -> int:
    """
    Determine the winner of the Cat and Mouse game using retrograde analysis.
    
    Args:
        graph: Adjacency list where graph[a] lists all nodes connected to a.
               Mouse starts at node 1, cat at node 2, hole at node 0.
    
    Returns:
        0 if the game is a draw, 1 if mouse wins, 2 if cat wins.
    
    >>> cat_mouse_game([[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]])
    0
    >>> cat_mouse_game([[1,3],[0],[3],[0,2]])
    1
    """
    n = len(graph)
    ...
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8e3464 and 303bcb7.

⛔ Files ignored due to path filters (2)
  • algorithms/graphs/cat_and_mouse/images/examples/cat_and_mouse_example_1.png is excluded by !**/*.png
  • algorithms/graphs/cat_and_mouse/images/examples/cat_and_mouse_example_2.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • DIRECTORY.md
  • algorithms/graphs/cat_and_mouse/README.md
  • algorithms/graphs/cat_and_mouse/__init__.py
  • algorithms/graphs/cat_and_mouse/test_cat_and_mouse.py
🧰 Additional context used
🧬 Code graph analysis (1)
algorithms/graphs/cat_and_mouse/test_cat_and_mouse.py (1)
algorithms/graphs/cat_and_mouse/__init__.py (1)
  • cat_mouse_game (5-60)
🪛 LanguageTool
algorithms/graphs/cat_and_mouse/README.md

[style] ~18-~18: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...use reaches the Hole, the Mouse wins. - If ever a position is repeated (i.e., the ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~79-~79: Consider using “who” when you are referring to a person instead of an object.
Context: ...mediate coloring"): If there is a child that is colored MOUSE, then this node will a...

(THAT_WHO)


[uncategorized] ~96-~96: Did you mean the adverb “anymore”?
Context: ...x works. Say we cannot color any nodes any more, and say from any node colored CAT or M...

(ANY_MORE)

🪛 markdownlint-cli2 (0.18.1)
DIRECTORY.md

90-90: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


91-91: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


113-113: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


114-114: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)


328-328: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


329-329: Unordered list indentation
Expected: 4; Actual: 6

(MD007, ul-indent)

algorithms/graphs/cat_and_mouse/README.md

45-45: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)


46-46: Reference links and images should use a label that is defined
Missing link or image reference definition: "j"

(MD052, reference-links-images)

🔇 Additional comments (3)
algorithms/graphs/cat_and_mouse/test_cat_and_mouse.py (1)

1-20: LGTM!

The test file is well-structured with parameterized tests that align with the examples documented in the README. Test cases correctly validate the expected outcomes (0 for draw, 1 for mouse win).

algorithms/graphs/cat_and_mouse/README.md (1)

1-116: LGTM!

The documentation comprehensively explains the Cat and Mouse game problem, constraints, and the minimax/percolation solution approach. The examples align with the test cases and implementation.

Note: The static analysis warnings about [j] on lines 45-46 are false positives—these represent array indexing notation (graph[i][j]), not markdown reference links.

algorithms/graphs/cat_and_mouse/__init__.py (1)

14-21: LGTM!

The parents function correctly computes predecessor states:

  • When it's cat's turn (t == 2), find mouse moves that led here
  • When it's mouse's turn (t == 1), find cat moves (excluding hole at node 0 via if c2:)

The 3 - t toggle elegantly switches between turns 1 and 2.

BrianLusina and others added 3 commits January 8, 2026 07:24
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@BrianLusina BrianLusina merged commit 8c30b66 into main Jan 8, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Algorithm Algorithm Problem Array Array data structure Datastructures Datastructures Depth First Search Documentation Documentation Updates enhancement Graph Graph data structures and algorithms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants