Skip to content

feat(algorithms, dynamic-programming): house robber 3#185

Merged
BrianLusina merged 1 commit intomainfrom
feat/algorithms-dynamic-programming-house-robber-3
Mar 3, 2026
Merged

feat(algorithms, dynamic-programming): house robber 3#185
BrianLusina merged 1 commit intomainfrom
feat/algorithms-dynamic-programming-house-robber-3

Conversation

@BrianLusina
Copy link
Owner

@BrianLusina BrianLusina commented Mar 3, 2026

Describe your change:

House robber 3 dynamic programming with binary tree

  • 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

Release Notes

  • New Features

    • Added House Robber III algorithm with support for binary tree structures. Three solution approaches now available: recursion, top-down dynamic programming with memoisation, and bottom-up dynamic programming.
  • Documentation

    • Comprehensive guide added for House Robber III, including constraints, examples, and algorithmic complexity analysis.
  • Tests

    • Refactored test suite with expanded parameterised test coverage for both numeric and tree-based robber scenarios.

@BrianLusina BrianLusina self-assigned this Mar 3, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

This pull request introduces House Robber III, a binary tree variant of the classic house robber dynamic programming problem, with three solution approaches (recursion, top-down DP with memoization, bottom-up DP), comprehensive documentation detailing constraints and complexity analyses, and refactored parameterized test suite.

Changes

Cohort / File(s) Summary
Documentation
algorithms/dynamic_programming/house_robber/README.md
Added comprehensive guide for House Robber III binary tree variant, including problem definition, constraints, examples, three solution approaches, complexity analyses, and common pitfalls.
Core Implementation
algorithms/dynamic_programming/house_robber/__init__.py
Added three new public functions for House Robber III: rob_iii_recursion, rob_iii_dynamic_programming_top_down, and rob_iii_dynamic_programming_bottom_up. Introduced imports for Optional, Dict, and BinaryTreeNode.
Test Suite
algorithms/dynamic_programming/house_robber/test_house_robber.py
Refactored tests from individual methods to parameterised test suite with RobTestCase class. Added ROB_TEST_CASES and ROB_III_TEST_CASES constants covering numeric and binary tree scenarios respectively.

Sequence Diagram

sequenceDiagram
    participant Client
    participant rob_iii_recursion
    participant BinaryTreeNode
    participant rob_iii_dp_top_down
    participant Memo

    Client->>rob_iii_recursion: Call with root
    rob_iii_recursion->>BinaryTreeNode: Visit node
    alt Has left child
        rob_iii_recursion->>rob_iii_recursion: Recursively visit left
    end
    alt Has right child
        rob_iii_recursion->>rob_iii_recursion: Recursively visit right
    end
    rob_iii_recursion-->>Client: Return max robbery amount

    Client->>rob_iii_dp_top_down: Call with root
    rob_iii_dp_top_down->>Memo: Check if node memoised
    alt Memoised
        Memo-->>rob_iii_dp_top_down: Return cached result
    else Not memoised
        rob_iii_dp_top_down->>BinaryTreeNode: Visit node
        rob_iii_dp_top_down->>rob_iii_dp_top_down: Recursively visit children
        rob_iii_dp_top_down->>Memo: Store result
    end
    rob_iii_dp_top_down-->>Client: Return max robbery amount
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Suggested labels

enhancement, Algorithm, Datastructures, Documentation, Dynamic Programming

Poem

🐰 Through binary trees a rabbit hops with care,
Three ways to rob the houses fair!
Recursion, memos, bottom-up with might,
Dynamic wisdom shines so bright! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.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 clearly summarizes the main change: adding House Robber 3, a binary tree variant of the House Robber dynamic programming algorithm.
Description check ✅ Passed The description is complete with a clear change summary and all required checklist items marked as completed, indicating adherence to repository guidelines.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/algorithms-dynamic-programming-house-robber-3

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.

@BrianLusina BrianLusina added enhancement Algorithm Algorithm Problem Datastructures Datastructures Documentation Documentation Updates Backtracking Backtracking Algorithm Hash Map Hash Map Data structure Dynamic Programming Dynamic Programming algorithm Trees Binary Tree Depth First Search Recursion labels Mar 3, 2026
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

🧹 Nitpick comments (2)
algorithms/dynamic_programming/house_robber/test_house_robber.py (1)

20-127: Prefer factory-built trees per case to avoid shared mutable fixtures.

ROB_III_TEST_CASES currently reuses the same BinaryTreeNode instances across multiple tests. Generating a fresh tree per case will keep tests isolated and future-proof against accidental node mutation.

🧪 Suggested pattern
-ROB_III_TEST_CASES = [
-    (BinaryTreeNode(...), 7),
-]
+ROB_III_TEST_CASES = [
+    (lambda: BinaryTreeNode(...), 7),
+]

 `@parameterized.expand`(ROB_III_TEST_CASES)
-def test_rob_iii_recursion(self, root: BinaryTreeNode, expected: int):
+def test_rob_iii_recursion(self, root_factory, expected: int):
+    root = root_factory()
     actual = rob_iii_recursion(root)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@algorithms/dynamic_programming/house_robber/test_house_robber.py` around
lines 20 - 127, ROB_III_TEST_CASES currently constructs BinaryTreeNode objects
once and reuses those same node instances across cases; instead, make each case
produce a fresh tree by replacing concrete BinaryTreeNode constructions with
factory callables (e.g., lambdas or small helper functions) that return a new
BinaryTreeNode root when invoked. Update ROB_III_TEST_CASES to store tuples like
(lambda: BinaryTreeNode(...), expected) and change the test harness to call the
factory before passing the tree into the functions under test so each run gets a
newly-built tree; reference the ROB_III_TEST_CASES symbol and BinaryTreeNode
constructors when implementing the factories.
algorithms/dynamic_programming/house_robber/README.md (1)

36-36: Polish wording for consistency in two places.

Line 36: use “directly linked” (no hyphen).
Line 79: use “Top-Down” to match the section heading style.

✏️ Suggested markdown edits
- in this place form a binary tree. It will automatically contact the police if two directly-linked houses were broken
+ in this place form a binary tree. It will automatically contact the police if two directly linked houses were broken

- 2. [Dynamic Programming(Memoization) - Top Down Approach](`#dynamic-programmingmemoization-top-down-approach`)
+ 2. [Dynamic Programming(Memoization) - Top-Down Approach](`#dynamic-programmingmemoization-top-down-approach`)

Also applies to: 79-79

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@algorithms/dynamic_programming/house_robber/README.md` at line 36, Update the
wording for consistency: replace the hyphenated phrase "directly-linked" with
"directly linked" in the sentence "It will automatically contact the police if
two directly-linked houses were broken" (look for that exact sentence in the
README) and change the section/phrase "Top down" to title-case "Top-Down" to
match the section heading style (search for "Top down" around the Top-Down
section header).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@algorithms/dynamic_programming/house_robber/__init__.py`:
- Around line 17-80: All three functions (rob_iii_recursion,
rob_iii_dynamic_programming_top_down, rob_iii_dynamic_programming_bottom_up) can
crash on skewed trees due to Python recursion limits; add a recursion-depth
guard and a non-recursive fallback: detect current recursion depth (pass a depth
counter or check sys.getrecursionlimit() vs current frame depth) and when depth
approaches the limit (e.g. > 900) switch to an iterative implementation that
uses an explicit stack/post-order traversal with a memo dict (key by node id or
node reference) to compute the same include/exclude values (for bottom_up
compute [include, exclude] per node iteratively; for top_down perform memoized
DFS with an explicit stack or simulate recursion using a stack of frames), and
have rob_iii_recursion call the top_down or bottom_up iterative fallback so all
three handle deep/skewed trees without RecursionError.

---

Nitpick comments:
In `@algorithms/dynamic_programming/house_robber/README.md`:
- Line 36: Update the wording for consistency: replace the hyphenated phrase
"directly-linked" with "directly linked" in the sentence "It will automatically
contact the police if two directly-linked houses were broken" (look for that
exact sentence in the README) and change the section/phrase "Top down" to
title-case "Top-Down" to match the section heading style (search for "Top down"
around the Top-Down section header).

In `@algorithms/dynamic_programming/house_robber/test_house_robber.py`:
- Around line 20-127: ROB_III_TEST_CASES currently constructs BinaryTreeNode
objects once and reuses those same node instances across cases; instead, make
each case produce a fresh tree by replacing concrete BinaryTreeNode
constructions with factory callables (e.g., lambdas or small helper functions)
that return a new BinaryTreeNode root when invoked. Update ROB_III_TEST_CASES to
store tuples like (lambda: BinaryTreeNode(...), expected) and change the test
harness to call the factory before passing the tree into the functions under
test so each run gets a newly-built tree; reference the ROB_III_TEST_CASES
symbol and BinaryTreeNode constructors when implementing the factories.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 669d7ef and 36baef6.

⛔ Files ignored due to path filters (20)
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_1.1.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_1.2.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_1.3.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_1.4.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_1.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_2.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_3.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/examples/house_robber_3_example_4.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_1.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_10.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_11.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_12.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_2.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_3.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_4.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_5.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_6.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_7.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_8.png is excluded by !**/*.png
  • algorithms/dynamic_programming/house_robber/images/solutions/house_robber_iii_solution_dp_bottom_up_9.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • algorithms/dynamic_programming/house_robber/README.md
  • algorithms/dynamic_programming/house_robber/__init__.py
  • algorithms/dynamic_programming/house_robber/test_house_robber.py

@BrianLusina BrianLusina merged commit 57e2116 into main Mar 3, 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 Backtracking Backtracking Algorithm Binary Tree Datastructures Datastructures Depth First Search Documentation Documentation Updates Dynamic Programming Dynamic Programming algorithm enhancement Hash Map Hash Map Data structure Recursion Trees

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant