Skip to content

Commit b45bd32

Browse files
authored
Update aliquot_sum.py
1 parent 5d9b6ad commit b45bd32

File tree

1 file changed

+48
-94
lines changed

1 file changed

+48
-94
lines changed

maths/aliquot_sum.py

Lines changed: 48 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,102 @@
1-
from __future__ import annotations # Enable modern type hints
1+
from __future__ import annotations
22

3+
import doctest
4+
from typing import overload, Tuple
5+
6+
@overload
7+
def aliquot_sum(input_num: int) -> int: ...
8+
@overload
9+
def aliquot_sum(input_num: int, return_factors: bool) -> Tuple[int, list[int]]: ...
310

411
def aliquot_sum(
512
input_num: int, return_factors: bool = False
6-
) -> int | tuple[int, list[int]]:
13+
) -> int | Tuple[int, list[int]]:
714
"""
8-
Calculates the aliquot sum of a positive integer. The aliquot sum is defined as
9-
the sum of all proper divisors of a number (all divisors except the number itself).
10-
11-
This implementation uses an optimized O(sqrt(n)) algorithm for efficiency.
12-
15+
Calculates the aliquot sum of a positive integer.
16+
The aliquot sum is the sum of all proper divisors of a number.
17+
1318
Args:
14-
input_num: Positive integer to calculate aliquot sum for
15-
return_factors: If True, returns tuple (aliquot_sum, sorted_factor_list)
16-
19+
input_num: Positive integer
20+
return_factors: If True, returns (sum, sorted_factor_list)
21+
1722
Returns:
18-
Aliquot sum if return_factors=False
19-
Tuple (aliquot_sum, sorted_factor_list) if return_factors=True
20-
23+
Aliquot sum or (sum, factors) if return_factors=True
24+
2125
Raises:
22-
TypeError: If input is not an integer
23-
ValueError: If input is not positive
24-
26+
TypeError: If input not integer
27+
ValueError: If input not positive
28+
2529
Examples:
2630
>>> aliquot_sum(15)
2731
9
2832
>>> aliquot_sum(15, True)
2933
(9, [1, 3, 5])
30-
>>> aliquot_sum(1)
31-
0
3234
"""
33-
# Validate input type - must be integer
35+
# Validate input
3436
if not isinstance(input_num, int):
3537
raise TypeError("Input must be an integer")
36-
37-
# Validate input value - must be positive
3838
if input_num <= 0:
3939
raise ValueError("Input must be positive integer")
40-
40+
4141
# Special case: 1 has no proper divisors
4242
if input_num == 1:
43-
# Return empty factor list if requested
4443
return (0, []) if return_factors else 0
45-
46-
# Initialize factors list with 1 (always a divisor)
44+
45+
# Initialize factors and total
4746
factors = [1]
48-
total = 1 # Start sum with 1
49-
50-
# Calculate square root as optimization boundary
47+
total = 1
5148
sqrt_num = int(input_num**0.5)
52-
53-
# Iterate potential divisors from 2 to square root
49+
50+
# Find factors efficiently
5451
for divisor in range(2, sqrt_num + 1):
55-
# Check if divisor is a factor
5652
if input_num % divisor == 0:
57-
# Add divisor to factors list
5853
factors.append(divisor)
5954
total += divisor
60-
61-
# Calculate complement (pair factor)
6255
complement = input_num // divisor
63-
64-
# Avoid duplicate for perfect squares
6556
if complement != divisor:
6657
factors.append(complement)
6758
total += complement
68-
69-
# Sort factors for consistent output
59+
7060
factors.sort()
71-
72-
# Return based on return_factors flag
7361
return (total, factors) if return_factors else total
7462

75-
7663
def classify_number(n: int) -> str:
7764
"""
78-
Classifies a number based on its aliquot sum:
79-
- Perfect: aliquot sum = number
80-
- Abundant: aliquot sum > number
81-
- Deficient: aliquot sum < number
82-
83-
Args:
84-
n: Positive integer to classify
85-
86-
Returns:
87-
Classification string ("Perfect", "Abundant", or "Deficient")
88-
89-
Raises:
90-
ValueError: If input is not positive
91-
65+
Classifies number based on aliquot sum:
66+
- Perfect: sum = number
67+
- Abundant: sum > number
68+
- Deficient: sum < number
69+
9270
Examples:
9371
>>> classify_number(6)
9472
'Perfect'
9573
>>> classify_number(12)
9674
'Abundant'
97-
>>> classify_number(19)
98-
'Deficient'
9975
"""
100-
# Validate input
10176
if n <= 0:
10277
raise ValueError("Input must be positive integer")
103-
104-
# Special case: 1 is always deficient
10578
if n == 1:
10679
return "Deficient"
107-
108-
# Explicitly request integer-only aliquot sum
109-
s = aliquot_sum(n, return_factors=False)
110-
111-
# Determine classification
80+
81+
s = aliquot_sum(n) # Always returns int
11282
if s == n:
11383
return "Perfect"
114-
elif s > n:
115-
return "Abundant"
116-
else:
117-
return "Deficient"
118-
84+
return "Abundant" if s > n else "Deficient"
11985

12086
if __name__ == "__main__":
121-
import doctest
122-
123-
# Run embedded doctests for verification
12487
doctest.testmod()
125-
126-
# Additional demonstration examples
127-
print("Aliquot sum of 28:", aliquot_sum(28)) # Perfect number
128-
129-
# Get factors for 28 with type-safe access
130-
factor_result = aliquot_sum(28, return_factors=True)
131-
# Since we requested factors, we know it's a tuple
132-
print("Factors of 28:", factor_result[1])
133-
88+
89+
print("Aliquot sum of 28:", aliquot_sum(28))
90+
91+
# Handle tuple return explicitly
92+
result = aliquot_sum(28, True)
93+
if isinstance(result, tuple):
94+
print("Factors of 28:", result[1])
95+
13496
print("Classification of 28:", classify_number(28))
135-
136-
# Large number performance test with targeted exception handling
97+
98+
# Large number test
13799
try:
138-
print("\nCalculating aliquot sum for 10^9...")
139-
print("Result:", aliquot_sum(10**9)) # 1497558336
100+
print("Aliquot sum for 10^9:", aliquot_sum(10**9))
140101
except (TypeError, ValueError) as e:
141-
# Handle input-related errors
142-
print(f"Input error: {e}")
143-
except MemoryError:
144-
# Handle potential memory issues with large numbers
145-
print("Memory error: Number too large")
146-
except OverflowError:
147-
# Handle numeric overflow
148-
print("Overflow error: Calculation too large")
102+
print(f"Error: {e}")

0 commit comments

Comments
 (0)