11from __future__ import annotations # Enable modern type hints
22
3+
34def aliquot_sum (
45 input_num : int , return_factors : bool = False
56) -> int | tuple [int , list [int ]]:
67 """
78 Calculates the aliquot sum of a positive integer. The aliquot sum is defined as
89 the sum of all proper divisors of a number (all divisors except the number itself).
9-
10+
1011 This implementation uses an optimized O(sqrt(n)) algorithm for efficiency.
11-
12+
1213 Args:
1314 input_num: Positive integer to calculate aliquot sum for
1415 return_factors: If True, returns tuple (aliquot_sum, sorted_factor_list)
15-
16+
1617 Returns:
1718 Aliquot sum if return_factors=False
1819 Tuple (aliquot_sum, sorted_factor_list) if return_factors=True
19-
20+
2021 Raises:
2122 TypeError: If input is not an integer
2223 ValueError: If input is not positive
23-
24+
2425 Examples:
2526 >>> aliquot_sum(15)
2627 9
@@ -32,42 +33,42 @@ def aliquot_sum(
3233 # Validate input type - must be integer
3334 if not isinstance (input_num , int ):
3435 raise TypeError ("Input must be an integer" )
35-
36+
3637 # Validate input value - must be positive
3738 if input_num <= 0 :
3839 raise ValueError ("Input must be positive integer" )
39-
40+
4041 # Special case: 1 has no proper divisors
4142 if input_num == 1 :
4243 # Return empty factor list if requested
4344 return (0 , []) if return_factors else 0
44-
45+
4546 # Initialize factors list with 1 (always a divisor)
46- factors = [1 ]
47+ factors = [1 ]
4748 total = 1 # Start sum with 1
48-
49+
4950 # Calculate square root as optimization boundary
5051 sqrt_num = int (input_num ** 0.5 )
51-
52+
5253 # Iterate potential divisors from 2 to square root
5354 for divisor in range (2 , sqrt_num + 1 ):
5455 # Check if divisor is a factor
5556 if input_num % divisor == 0 :
5657 # Add divisor to factors list
5758 factors .append (divisor )
5859 total += divisor
59-
60+
6061 # Calculate complement (pair factor)
6162 complement = input_num // divisor
62-
63+
6364 # Avoid duplicate for perfect squares
64- if complement != divisor :
65+ if complement != divisor :
6566 factors .append (complement )
6667 total += complement
67-
68+
6869 # Sort factors for consistent output
6970 factors .sort ()
70-
71+
7172 # Return based on return_factors flag
7273 return (total , factors ) if return_factors else total
7374
@@ -78,16 +79,16 @@ def classify_number(n: int) -> str:
7879 - Perfect: aliquot sum = number
7980 - Abundant: aliquot sum > number
8081 - Deficient: aliquot sum < number
81-
82+
8283 Args:
8384 n: Positive integer to classify
84-
85+
8586 Returns:
8687 Classification string ("Perfect", "Abundant", or "Deficient")
87-
88+
8889 Raises:
8990 ValueError: If input is not positive
90-
91+
9192 Examples:
9293 >>> classify_number(6)
9394 'Perfect'
@@ -99,14 +100,14 @@ def classify_number(n: int) -> str:
99100 # Validate input
100101 if n <= 0 :
101102 raise ValueError ("Input must be positive integer" )
102-
103+
103104 # Special case: 1 is always deficient
104105 if n == 1 :
105106 return "Deficient"
106-
107+
107108 # Explicitly request integer-only aliquot sum
108109 s = aliquot_sum (n , return_factors = False )
109-
110+
110111 # Determine classification
111112 if s == n :
112113 return "Perfect"
@@ -118,20 +119,20 @@ def classify_number(n: int) -> str:
118119
119120if __name__ == "__main__" :
120121 import doctest
121-
122+
122123 # Run embedded doctests for verification
123124 doctest .testmod ()
124-
125+
125126 # Additional demonstration examples
126127 print ("Aliquot sum of 28:" , aliquot_sum (28 )) # Perfect number
127-
128+
128129 # Get factors for 28 with type-safe access
129130 factor_result = aliquot_sum (28 , return_factors = True )
130131 # Since we requested factors, we know it's a tuple
131132 print ("Factors of 28:" , factor_result [1 ])
132-
133+
133134 print ("Classification of 28:" , classify_number (28 ))
134-
135+
135136 # Large number performance test with targeted exception handling
136137 try :
137138 print ("\n Calculating aliquot sum for 10^9..." )
0 commit comments