Skip to content

Add improved doctrings and doctests for math/perfect_number.py #12830

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
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Jul 6, 2025
commit b6ea72123db1af3df6d882cc81c20d2ba1b94e34
66 changes: 33 additions & 33 deletions maths/perfect_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,38 +126,38 @@ def perfect(number: int) -> bool:
"""
if not isinstance(number, int):
raise ValueError("number must be an integer")

if number <= 0:
return False

# Special case: 1 has no proper divisors
if number == 1:
return False

# Find sum of all proper divisors
# We only need to check up to number//2 since no proper divisor
# can be greater than half the number
divisor_sum = sum(i for i in range(1, number // 2 + 1) if number % i == 0)

return divisor_sum == number


def perfect_optimized(number: int) -> bool:
"""
Optimized version of perfect number checker using mathematical properties.

This version uses the fact that divisors come in pairs (d, n/d) to reduce
the search space to sqrt(n).

Time Complexity: O(sqrt(n))
Space Complexity: O(1)

Args:
number: The positive integer to be checked.

Returns:
True if the number is a perfect number, False otherwise.

Examples:
>>> perfect_optimized(6)
True
Expand All @@ -176,12 +176,12 @@ def perfect_optimized(number: int) -> bool:
"""
if not isinstance(number, int):
raise ValueError("number must be an integer")

if number <= 1:
return False

divisor_sum = 1 # 1 is always a proper divisor for n > 1

# Check divisors up to sqrt(number)
i = 2
while i * i <= number:
Expand All @@ -191,20 +191,20 @@ def perfect_optimized(number: int) -> bool:
if i != number // i:
divisor_sum += number // i
i += 1

return divisor_sum == number


def find_perfect_numbers(limit: int) -> list[int]:
"""
Find all perfect numbers up to a given limit.

Args:
limit: The upper bound to search for perfect numbers.

Returns:
List of perfect numbers up to the limit.

Examples:
>>> find_perfect_numbers(10)
[6]
Expand All @@ -219,20 +219,20 @@ def find_perfect_numbers(limit: int) -> list[int]:
"""
if not isinstance(limit, int) or limit < 0:
raise ValueError("limit must be a non-negative integer")

return [n for n in range(1, limit + 1) if perfect(n)]


def get_divisors(number: int) -> list[int]:
"""
Get all proper divisors of a number (excluding the number itself).

Args:
number: The positive integer to find divisors for.

Returns:
List of proper divisors in ascending order.

Examples:
>>> get_divisors(6)
[1, 2, 3]
Expand All @@ -247,10 +247,10 @@ def get_divisors(number: int) -> list[int]:
"""
if not isinstance(number, int) or number <= 0:
raise ValueError("number must be a positive integer")

if number == 1:
return []

return [i for i in range(1, number // 2 + 1) if number % i == 0]


Expand All @@ -259,46 +259,46 @@ def get_divisors(number: int) -> list[int]:

print("Running doctests...")
testmod(verbose=True)

print("\nPerfect Number Checker")
print("=" * 40)
print("A perfect number equals the sum of its proper divisors.")
print("Examples: 6 (1+2+3), 28 (1+2+4+7+14), 496, 8128, ...")
print()

while True:
try:
user_input = input("Enter a positive integer (or 'q' to quit): ").strip()
if user_input.lower() == 'q':
if user_input.lower() == "q":
break

number = int(user_input)

if number <= 0:
print("Please enter a positive integer.")
continue

is_perfect = perfect(number)
divisors = get_divisors(number)
divisor_sum = sum(divisors)

print(f"\nNumber: {number}")
print(f"Proper divisors: {divisors}")
print(f"Sum of divisors: {divisor_sum}")
print(f"Is perfect: {'Yes' if is_perfect else 'No'}")

if is_perfect:
print(f"✓ {number} is a Perfect Number!")
else:
print(f"✗ {number} is not a Perfect Number.")

print("-" * 40)

except ValueError as e:
if "invalid literal" in str(e):
print("Please enter a valid integer.")
else:
print(f"Error: {e}")
except KeyboardInterrupt:
print("\nGoodbye!")
break
break
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy