Skip to content

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Improve code with caches#202

Open
Iswanna wants to merge 4 commits into
CodeYourFuture:mainfrom
Iswanna:improve-code-with-caches
Open

West Midlands | 26 March SDC | Iswat Bello | Sprint 2 | Improve code with caches#202
Iswanna wants to merge 4 commits into
CodeYourFuture:mainfrom
Iswanna:improve-code-with-caches

Conversation

@Iswanna

@Iswanna Iswanna commented Jul 1, 2026

Copy link
Copy Markdown

Learners, PR Template

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

In this PR, I have optimised the Fibonacci and Making Change recursive algorithms by implementing manual memoisation. These changes transform functions that previously had exponential time complexity into efficient, linear-time operations.

A comprehensive breakdown of the logic, state-tracking strategies, and specific code changes is provided in the CHANGES_MADE.md file included in this PR.

Key Improvements

1. Fibonacci Sequence

  • Performance: Reduced time complexity from $O(2^n)$ to $O(term_index)$.
  • Caching: Implemented a dictionary-based memo to store and reuse results of previously calculated terms.
  • Readability: Renamed the parameter to term_index and added type hints to clarify the function's purpose.

2. Making Change Algorithm

  • State Tracking: Developed a unique cache key using a Tuple (total, len(coins)) to track sub-problems based on both the remaining amount and available denominations.
  • Structural Refactor: Introduced a helper/wrapper pattern. The wrapper ensures the cache is cleared between different calls, while the helper manages the recursive logic.
  • Legacy Integrity: Maintained the original variable names from the legacy code to ensure continuity while improving underlying performance.

Testing Done

All implementations were verified against the provided test suites:

  • Fibonacci: Confirmed that fibonacci(200) now returns results instantly.
  • Making Change: Verified that test_9176 (which produces a result in the quadrillions) completes in milliseconds, demonstrating the efficiency of the cache.

Learning Reflection

These tasks served as a practical application of the Space-vs-Time trade-off. By "spending" memory (the memo dictionaries), I successfully "saved" massive amounts of CPU time, allowing the algorithms to scale to much larger inputs.

Iswanna added 4 commits July 1, 2026 17:24
- Implement a dictionary-based cache (memo) to store previously calculated terms
- Reduce time complexity from exponential O(2^n) to linear O(n)
- Rename parameter 'n' to 'term_index' for better descriptive clarity
- Add type hints and documentation for performance complexity
- Introduce 'memo' dictionary to cache results of recursive sub-problems
- Use a state tuple (total, len(coins)) as a unique cache key
- Refactor into a helper function to isolate recursive logic
- Add a wrapper function to clear the cache and provide default denominations
- Maintain legacy variable names to ensure code continuity
- Detail the transition from exponential O(2^n) to linear O(n) complexity
- Explain the use of state-tracking tuples in the making_change algorithm
- Summarize the space-vs-time trade-offs applied to Fibonacci and Coin Change
- Document the refactoring into helper/wrapper patterns
@Iswanna Iswanna added 📅 Sprint 2 Assigned during Sprint 2 of this module Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. Module-Complexity The name of the module. labels Jul 1, 2026
@nedssoft nedssoft added Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Jul 1, 2026

@nedssoft nedssoft left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Iswat — this is genuinely strong work, and your CHANGES_MADE.md shows you really understand what you did rather than just pattern-matching. Turning both of these from exponential down to linear with a hand-rolled cache, and being able to articulate the space-vs-time trade-off, is exactly the insight this exercise is chasing. 👏 A couple of touches I liked: renaming nterm_index so the Fibonacci function reads clearly, and choosing an immutable tuple for the Making Change key with a stated reason why.

One optional question inline — it's about the shape of your cache, not its correctness (your logic is sound and the whole test suite passes). You've nailed the task, so I'm marking this Complete. Lovely work. 🎉

(For your curiosity only: now that you've built memoisation by hand — which is the whole point of this exercise — it's worth peeking at Python's functools.cache / lru_cache. It's a one-line decorator that does exactly what your memo dict does. Something to explore later, nothing to change here.)


def ways_to_make_change(total: int) -> int:
"""Wrapper that matches the legacy test suite signature."""
memo.clear()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You spotted something sharp here: because memo lives at module level and lingers between calls, you had to add memo.clear() so each fresh ways_to_make_change(...) doesn't reuse the previous call's cache. Nice catch — but needing to manually reset shared state is often a little hint worth listening to.

What do you think would happen if the memo dictionary instead lived inside ways_to_make_change — created fresh on each call — and the helper used that one (say, as a nested function, or by passing it down)? Would you still need to remember to .clear() it at all?

Your current version is correct — this is purely about making it harder to get wrong later. Something to turn over when you're curious.

@nedssoft nedssoft added Complete Volunteer to add when work is complete and all review comments have been addressed. and removed Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. labels Jul 1, 2026
@Iswanna

Iswanna commented Jul 4, 2026

Copy link
Copy Markdown
Author

Iswat — this is genuinely strong work, and your CHANGES_MADE.md shows you really understand what you did rather than just pattern-matching. Turning both of these from exponential down to linear with a hand-rolled cache, and being able to articulate the space-vs-time trade-off, is exactly the insight this exercise is chasing. 👏 A couple of touches I liked: renaming nterm_index so the Fibonacci function reads clearly, and choosing an immutable tuple for the Making Change key with a stated reason why.

One optional question inline — it's about the shape of your cache, not its correctness (your logic is sound and the whole test suite passes). You've nailed the task, so I'm marking this Complete. Lovely work. 🎉

(For your curiosity only: now that you've built memoisation by hand — which is the whole point of this exercise — it's worth peeking at Python's functools.cache / lru_cache. It's a one-line decorator that does exactly what your memo dict does. Something to explore later, nothing to change here.)

Thank you so much for the feedback! I'm glad the renaming to term_index made the logic clearer to read.
I've noted your suggestion about lru_cache and will definitely explore how that replaces my hand-rolled dictionary. Thanks for marking this PR complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Complete Volunteer to add when work is complete and all review comments have been addressed. Module-Complexity The name of the module. 📅 Sprint 2 Assigned during Sprint 2 of this module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants