Start learning free

LESSON 203 OF 414 · FUNCTIONS & CLASSES

Magical Number in Scala: Repeated Digit Sums with while Loops

Practice O(log n) Read the full explanation

A magical number is obtained from a positive number by adding its digits repeatedly until we obtain one digit.

Example 1:

Input: N = 39
Output: 3
Explanation: 39 → 3 + 9 = 12 → 1 + 2 = 3

Example 2:

Input: N = 928435
Output: 4
Explanation: 9 + 2 + 8 + 4 + 3 + 5 = 31 → 3 + 1 = 4

STEP 1 OF 9
    Ctrl + Enter to check

    SCALA · FUNCTIONS & CLASSES

    Magical Number in Scala, explained

    Problem overview

    The method magicNumber takes a positive Int named n. It adds up the digits of the number, then adds up the digits of that sum, and keeps going until a single digit is left. That digit is the answer.

    For 39: the digits give 3 + 9 = 12, and 12 gives 1 + 2 = 3, so the result is 3. For 928435: 9 + 2 + 8 + 4 + 3 + 5 = 31, then 3 + 1 = 4, so the result is 4.

    Approach: two small loops

    The task splits into two parts that are easier to write separately:

    1. A helper, digitSum, that adds up all the digits of a number.
    2. An outer loop in magicNumber that applies the helper again and again while the number still has more than one digit.

    To get the digits without turning the number into text, use arithmetic. The remainder after dividing by 10, written num % 10, is the last digit. Integer division by 10, num / 10, discards that digit and shifts the others one place to the right. Repeating this takes the digits off one at a time, from the last to the first, until nothing is left.

    The outer loop always ends. A number with two or more digits is larger than its digit sum, so each pass makes the number smaller, and once it is below 10, the loop stops.

    Step by step

    The lesson writes the outer method first and assumes the helper exists.

    1. Copy the parameter into a variable. A method parameter is a val and can't be reassigned, so var num = n gives the loop something to change.
    2. Loop while the number has at least two digits, which is exactly when num > 9.
    3. Replace the number by its digit sum: num = digitSum(num).
    4. Return num after the loop, when it has one digit.
    5. Write digitSum above it, taking an Int named n and returning an Int. It starts with its own var num = n, for the same reason as before.
    6. Declare sum as a var set to 0. No digit has been added yet.
    7. Loop while num > 0. A digit is still left exactly while the number is positive.
    8. Add the last digit with sum += num % 10.
    9. Remove the last digit with num /= 10. Dividing two Int values drops the fraction, so only the integer part stays.
    10. Return sum after the loop.

    The solution in Scala

    class Solution {
        def digitSum(n: Int): Int = {
            var num = n
            var sum = 0
            while (num > 0) {
                sum += num % 10
                num /= 10
            }
            return sum
        }
    
        def magicNumber(n: Int): Int = {
            var num = n
            while (num > 9) {
                num = digitSum(num)
            }
            return num
        }
    }
    

    The Scala details worth knowing:

    • Parameters are vals. Assigning to n directly is a compile error, so each method copies it into a local var.
    • Integer division truncates. 39 / 10 is 3, not 3.9, and 39 % 10 is 9. Together they split 39 into its last digit and the rest.
    • Compound assignment. sum += x means sum = sum + x, and num /= 10 means num = num / 10. Scala has no ++ or -- operators, but it does have these.
    • Methods can call each other in any order inside a class, so digitSum may be defined above or below magicNumber.
    • return is optional. Ending each method with just sum or num means the same thing.

    A worked trace

    For n = 928435, the first call to digitSum peels off 5, 3, 4, 8, 2, 9, in that order, and returns 31. Because 31 is above 9, the outer loop calls digitSum(31), which returns 1 + 3 = 4. Now num is 4, the loop condition fails, and the method returns 4.

    Complexity

    Time: about O(log n). digitSum runs once per digit, and a number n has about the base-10 logarithm of n digits. The first call shrinks the value dramatically. For any Int, the digit sum is at most 82, so every later pass handles one or two digits. The total work is dominated by the first call.

    Space: O(1). Only a few integer variables are used.

    Edge cases and common mistakes

    • Already one digit. magicNumber(9) skips the loop and returns 9.
    • Multiples of 10. 10 becomes 1 + 0 = 1. Zeros contribute nothing, and digitSum(1230) is 6.
    • Zero. magicNumber(0) returns 0, because 0 is not above 9. The task says the input is positive, so this is only a bonus.
    • Largest Int. 2147483647 has digit sum 46, then 4 + 6 = 10, then 1, so the answer is 1. Nothing overflows, because the sums are tiny.
    • Negative numbers. num % 10 is negative for a negative num and the loop condition num > 9 is false, so a negative input is returned unchanged.
    • Using num > 10. That would leave 10 unprocessed and return 10 instead of 1.
    • Using while (num > 1) in digitSum. A leading digit of 1 is never added, so digitSum(10) would return 0 instead of 1. The loop must continue while num > 0.
    • Returning inside the loop. The return belongs after the loop; inside it, the method would stop after the first pass.

    Testing

    • 39 gives 3.
    • 928435 gives 4.
    • 9 gives 9, and 10 gives 1.
    • 2147483647 gives 1.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free