Problem overview
A magical number comes from a positive integer n by adding its digits, then adding the digits of that sum, and so on until only one digit is left. The method magicNumber returns that single digit.
For n = 39, the digits add to 3 + 9 = 12. That still has two digits, so add again: 1 + 2 = 3. The answer is 3. For n = 928435, 9 + 2 + 8 + 4 + 3 + 5 = 31, then 3 + 1 = 4, so the answer is 4.
A different meaning of "magic number"
In everyday Python, a "magic number" usually means something else: a literal value in the code with no name, such as if age > 18, where a reader has to guess what 18 stands for. The fix is a named constant like ADULT_AGE = 18. This lesson is about a different idea: the number you get by adding digits repeatedly. In maths it is called the digital root.
Approach: split the work into two small jobs
The task has two parts, and each is easy by itself:
- Add up all the digits of a number. This is the helper
digitSum. - Repeat that until the number has one digit. This is the loop in
magicNumber.
The repeating loop terminates because the digit sum of a number with two or more digits is always smaller than the number. For 39 the sum is 12, and for 12 the sum is 3. The value strictly decreases, and it cannot go below 1 for a positive input, so the loop ends.
Getting the digits with % and //
Python has no direct way to loop over the digits of an integer, but two operators do the job. n % 10 is the last digit, and n // 10 is the number with the last digit removed:
n = 39
print(n % 10) # 9
print(n // 10) # 3
print(divmod(39, 10)) # (3, 9)
Repeating this until nothing is left visits every digit, starting from the last.
Step by step
- Write the outer loop first, as
while n > 9. A number has two or more digits exactly when it is greater than 9. - Replace
nwith its digit sum inside the loop:n = self.digitSum(n). The helper is a method of the class, so it is called throughself. - Return
nafter the loop. It is the one-digit result. A return inside the loop would stop after the first round. - Write
digitSumas a method that takesselfandn. - Start a running total at 0, because no digit has been added yet.
- Loop while
n > 0, that is, while the number still has a digit. - Add the last digit with
n % 10. - Remove the last digit with
n //= 10. - Return the total after the loop.
The solution in Python
class Solution:
def digitSum(self, n):
sum = 0
while n > 0:
sum += n % 10
n //= 10
return sum
def magicNumber(self, n: int) -> int:
while n > 9:
n = self.digitSum(n)
return n
Python details to notice:
- Use
//=, not/=. The/operator always gives a float, so39 / 10is3.9, and the fractions would leak into the total. Starting from 39, a version withn /= 10returns13.333333333333332instead of 12. Floor division keeps everything an integer. - The name
sumhides a built-in. Python already has a function calledsum. InsidedigitSumthe local variable replaces it, which is harmless here because the built-in is never called. In other code, callingsum([1, 2])after assigningsum = 0fails with'int' object is not callable. A name such astotalavoids the problem. - Integers have no size limit. The method also works for a number with 25 digits, where a language with 64-bit integers would overflow.
- A string-based shortcut exists.
sum(int(c) for c in str(n))also gives the digit sum, for example 31 for 928435. The arithmetic version here avoids creating strings, and it is the pattern to learn.
Complexity
Time. digitSum takes one step per digit, so O(d) for a number with d digits, which is about log n. After the first round the number is at most 9 times the digit count, so it is tiny: a 12-digit number becomes at most 108. The later rounds cost a few steps each, so the whole method is O(log n) for practical purposes.
Space: O(1). Only a few integer variables are used.
A shortcut from number theory
The magical number follows a pattern. For a positive n it equals 1 + (n - 1) % 9. Adding digits does not change a number's remainder when divided by 9, so the repeated digit sum always lands on the digit with the same remainder, using 9 instead of 0. For 39 this gives 1 + 38 % 9 = 3, and for 928435 it gives 4. The formula runs in constant time, but the lesson asks for the loops to practise while and helper methods.
Edge cases and common mistakes
- Already one digit. For
n = 7the outer loop never runs, and the method returns 7. - Multiples of 9. Both 9 and 99 give 9, not 0. The sum of digits of a positive number is never 0.
- Numbers that need several rounds.
999999999999becomes 108, then 9. The outer loop is needed, and one call todigitSumis not enough. - Zero. The statement is about positive numbers. For
0the method returns 0, because the loop does not run. - Using
n > 10. That stops too early on 10, which has two digits. The right test isn > 9.
Testing
magicNumber(39)returns3.magicNumber(928435)returns4.magicNumber(10)returns1.magicNumber(99)returns9.magicNumber(7)returns7.
