Problem overview
The function magicNumber receives a positive integer n. Add its digits, and if the sum still has two or more digits, add the digits of the sum, and so on until one digit remains. That digit is the answer. For 39: 3 + 9 = 12, then 1 + 2 = 3, so the result is 3. For 928435: 9 + 2 + 8 + 4 + 3 + 5 = 31, then 3 + 1 = 4.
Approach
The task has two layers. The outer layer repeats a transformation until the number is small. The inner layer is the transformation itself, the sum of the digits of a number. Writing them as two functions keeps each one short: magicNumber assumes a helper digitSum exists, and digitSum is written afterwards.
The outer loop is guaranteed to finish. A number with two or more digits is larger than the sum of its digits (for example 39 becomes 12), so the value strictly shrinks each round and cannot stay above 9 forever.
Getting the digits uses arithmetic, not string conversion. The remainder of a division by 10 is the last digit, and dividing by 10 drops it, because integer division discards the remainder.
Step by step
magicNumber
- Loop while
nhas at least two digits, which meansn > 9. Go has nowhile, so this is aforwith only a condition. - In the loop, replace
nwithdigitSum(n). - After the loop,
nis a single digit. Return it.
digitSum
- Declare it with an
intparameter and anintresult. Go lets you define it aftermagicNumber, since top-level functions can appear in any order. - Start
sumat 0 with:=. - Loop while
n > 0. Each pass addsn % 10tosum, then doesn /= 10. - Return
sumafter the loop.
Tracing digitSum(39): 39 % 10 is 9, so sum is 9 and n becomes 3. Then 3 % 10 is 3, so sum is 12 and n becomes 0. The loop ends and the function returns 12.
The solution in Go
func magicNumber(n int) int {
for n > 9 {
n = digitSum(n)
}
return n
}
func digitSum(n int) int {
sum := 0
for n > 0 {
sum += n % 10
n /= 10
}
return sum
}
Language details worth knowing
Go passes arguments by value, so digitSum may change its own n to 0 without affecting the caller's variable. The same applies to magicNumber: assigning to the parameter n is fine and changes only the local copy.
The / operator on two int values truncates toward zero, so 39 / 10 is 3 and /= 10 removes the last digit. The % operator takes the sign of the dividend, so for negative input the digits would come out negative or the loop would never run. The lesson only uses positive numbers.
for n > 9 { ... } is Go's way of writing a while loop: a for with just a condition.
Splitting the work this way also makes testing easier. You can check digitSum alone: digitSum(39) is 12, digitSum(12) is 3, and digitSum(928435) is 31. If those are right, any mistake left is in the outer loop, and the outer loop has only three lines, so there is little left to go wrong.
Complexity
One call to digitSum costs O(d), where d is the number of digits, which is O(log n). After the first call the value is at most 9 times the digit count, so the later rounds work on tiny numbers, and the total is O(log n) time. Space is O(1): a few integer variables.
Tracing the larger example
For 928435, the first call of digitSum returns 31, which is still above 9, so the loop runs again. The second call turns 31 into 4 (3 + 1). Now 4 > 9 is false, the loop stops, and the function returns 4. Two rounds were enough, and the number of rounds stays small even for very large inputs, because every round shrinks the value dramatically.
A shortcut, for the curious
This result is known as the digital root, and for a positive n it equals 1 + (n-1) % 9. For 39 that is 1 + 38 % 9 = 1 + 2 = 3, and for 928435 it is 4, matching the loop. The loop version is the one to write here, because it shows the process the statement describes and doesn't depend on a number-theory fact.
Edge cases and common mistakes
- A single-digit input is returned immediately, because the loop condition is false at once.
magicNumber(7)is 7. - Multiples of 9 end at 9, not 0:
magicNumber(18)is 9, and so ismagicNumber(99999). - Putting
returninside the loop returns after one round, which gives 12 for input 39. - Using
n >= 9works for 9 too, butn > 9states the idea precisely: more than one digit. - Forgetting to assign the result of
digitSum(n)back tonleaves an endless loop.
Testing
39gives3.928435gives4.7gives7.18gives9.