Add narcissistic number finder with dynamic programming
Description
Adds a dynamic programming implementation to find all narcissistic numbers (also known as Armstrong numbers) up to a specified limit.
A narcissistic number is a number that equals the sum of its own digits each raised to the power of the number of digits. For example: 153 = 1³ + 5³ + 3³.
Implementation Details
- Uses memoization to cache digit power calculations (
digit^power) - Avoids redundant computations when checking multiple numbers
- Implements true dynamic programming with overlapping subproblems
Dynamic Programming Approach
Overlapping Subproblems: Many numbers share the same digits, so the same digit powers are computed repeatedly (e.g., 153, 351, 135 all need 1³, 5³, 3³)
Memoization: Cache stores (power, digit) -> result mappings to avoid recomputation
Optimal Substructure: The narcissistic property is built from individual digit power results
Examples
>>> find_narcissistic_numbers(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> find_narcissistic_numbers(1000)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407]
>>> find_narcissistic_numbers(10000)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474]
Type of Change
- [x] Add an algorithm
Checklist
- [x] I have read CONTRIBUTING.md
- [x] This pull request is all my own work -- I have not plagiarized
- [x] I know that pull requests will not be merged if they fail the automated tests
- [x] This PR only changes one algorithm file
- [x] All new Python files are placed inside an existing directory (
dynamic_programming/) - [x] Filename is in all lowercase characters with no spaces or dashes (
narcissistic_number.py) - [x] All functions and variable names follow Python naming conventions (snake_case)
- [x] All function parameters and return values are annotated with Python type hints
- [x] All functions have doctests that pass the automated testing (7 tests)
- [x] Algorithm includes a URL pointing to Wikipedia or similar explanation
- [x] Code uses Python 3.13+ features where appropriate
- [x] Code passes
ruff checklinting - [x] Code is formatted with
black(or follows PEP 8)
References
@poyea
@poyea, revisions applied.