-
-
Notifications
You must be signed in to change notification settings - Fork 49.6k
Add narcissistic number finder with dynamic programming #13971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AliAlimohammadi
wants to merge
6
commits into
TheAlgorithms:master
Choose a base branch
from
AliAlimohammadi:add-narcissistic-number-dp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
0aa3491
Add narcissistic number finder with dynamic programming
AliAlimohammadi 440b37e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 5b1fd5c
Update dynamic_programming/narcissistic_number.py
AliAlimohammadi 4e277e0
Update dynamic_programming/narcissistic_number.py
AliAlimohammadi 5a748de
Update dynamic_programming/narcissistic_number.py
AliAlimohammadi 0dec31a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| """ | ||
| Find all narcissistic numbers up to a given limit using dynamic programming. | ||
|
|
||
| A narcissistic number (also known as an Armstrong number or plus perfect number) | ||
| is a number that is the sum of its own digits each raised to the power of the | ||
| number of digits. | ||
|
|
||
| For example, 153 is a narcissistic number because 153 = 1^3 + 5^3 + 3^3. | ||
|
|
||
| This implementation uses dynamic programming with memoization to efficiently | ||
| compute digit powers and find all narcissistic numbers up to a specified limit. | ||
|
|
||
| The DP optimization caches digit^power calculations. When searching through many | ||
| numbers, the same digit power calculations occur repeatedly (e.g., 153, 351, 135 | ||
| all need 1^3, 5^3, 3^3). Memoization avoids these redundant calculations. | ||
|
|
||
| Examples of narcissistic numbers: | ||
| Single digit: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | ||
| Three digit: 153, 370, 371, 407 | ||
| Four digit: 1634, 8208, 9474 | ||
| Five digit: 54748, 92727, 93084 | ||
|
|
||
| Reference: https://en.wikipedia.org/wiki/Narcissistic_number | ||
| """ | ||
|
|
||
|
|
||
| def find_narcissistic_numbers(limit: int) -> list[int]: | ||
| """ | ||
| Find all narcissistic numbers up to the given limit using dynamic programming. | ||
|
|
||
| This function uses memoization to cache digit power calculations, avoiding | ||
| redundant computations across different numbers with the same digit count. | ||
|
|
||
| Args: | ||
| limit: The upper bound for searching narcissistic numbers (exclusive) | ||
|
|
||
| Returns: | ||
| list[int]: A sorted list of all narcissistic numbers below the limit | ||
|
|
||
| Examples: | ||
| >>> find_narcissistic_numbers(10) | ||
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
| >>> find_narcissistic_numbers(160) | ||
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153] | ||
| >>> find_narcissistic_numbers(400) | ||
| [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371] | ||
| >>> 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] | ||
| >>> find_narcissistic_numbers(1) | ||
| [0] | ||
| >>> find_narcissistic_numbers(0) | ||
| [] | ||
| """ | ||
| if limit <= 0: | ||
| return [] | ||
|
|
||
| narcissistic_nums = [] | ||
|
|
||
| # Memoization: cache[(power, digit)] = digit^power | ||
| # This avoids recalculating the same power for different numbers | ||
| power_cache: dict[tuple[int, int], int] = {} | ||
|
|
||
| def get_digit_power(digit: int, power: int) -> int: | ||
AliAlimohammadi marked this conversation as resolved.
Show resolved
Hide resolved
AliAlimohammadi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| """Get digit^power using memoization (DP optimization).""" | ||
| if (power, digit) not in power_cache: | ||
| power_cache[(power, digit)] = digit**power | ||
| return power_cache[(power, digit)] | ||
|
|
||
| # Check each number up to the limit | ||
| for number in range(limit): | ||
| # Count digits | ||
| num_digits = len(str(number)) | ||
AliAlimohammadi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Calculate sum of powered digits using memoized powers | ||
| remaining = number | ||
| digit_sum = 0 | ||
| while remaining > 0: | ||
| digit = remaining % 10 | ||
| digit_sum += get_digit_power(digit, num_digits) | ||
| remaining //= 10 | ||
|
|
||
| # Check if narcissistic | ||
| if digit_sum == number: | ||
| narcissistic_nums.append(number) | ||
|
|
||
| return narcissistic_nums | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| import doctest | ||
|
|
||
| doctest.testmod() | ||
|
|
||
| # Demonstrate the dynamic programming approach | ||
| print("Finding all narcissistic numbers up to 10000:") | ||
| print("(Using memoization to cache digit power calculations)") | ||
| print() | ||
|
|
||
| narcissistic_numbers = find_narcissistic_numbers(10000) | ||
| print(f"Found {len(narcissistic_numbers)} narcissistic numbers:") | ||
| print(narcissistic_numbers) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.