Start learning free

LESSON 181 OF 415 · LOOPS - CHALLENGES

Print Powers in Swift: A while Loop with Multiplication

Practice Read the full explanation

Given two non-negative integers A and B, print to the console all numbers less than or equal to B that are powers of A

Powers of a number are: A0, A1, A2, etc.

An = A multiplied by itself n times

A0 = 1
A1 = A
A2 = A * A
A3 = A * A * A
A4 = A * A * A * A
etc.

Example:

Input: A = 3, B = 100

Output:
1
3
9
27
81

Explanation:
30 = 1
31 = 3
32 = 9
33 = 27
34 = 81
Hints:

We start with the integer 1. We should repeatedly do some instructions (print it then multiply it by A) as long as one condition is satisfied (current power <= B). Sounds familiar?

We should use a variable power, initially equal to 1, in order to store the current power. And we should use a loop (a while loop, or in languages without one a condition-only for loop) to repeatedly check if power <= B and if so, print and update power. How will the code look like?

Set power to 1. While power is less than or equal to B: print power, then multiply power by A.

STEP 1 OF 4
    Ctrl + Enter to check

    SWIFT · LOOPS - CHALLENGES

    Print Powers in Swift, explained

    Problem overview

    The method printPowers(_ A: Int, _ B: Int) receives two non-negative integers and prints, one per line, every power of A that is less than or equal to B, starting at A⁰ = 1. It returns nothing: the result is the text it prints.

    For A = 3 and B = 100 the output is 1, 3, 9, 27 and 81. The next power, 243, is larger than 100, so printing stops.

    Approach

    You don't need an exponent or a power function. Each power is the previous one multiplied by A: 1, then 1 * 3 = 3, then 3 * 3 = 9. So keep one variable holding the current power. While it is at most B, print it and multiply it by A. The first value that exceeds B fails the loop condition, and the loop ends. Because the powers only grow, no later power can be small enough to print.

    Step by step

    1. Declare power with var and set it to 1. It changes on every iteration, so it can't be a let. Starting at 1 means A⁰ is the first candidate.
    2. Write a while loop whose condition is power <= B. Swift needs no parentheses around the condition, but the braces are required.
    3. Print power inside the loop with print, which ends each output with a newline.
    4. Move to the next power with power *= A. Without this line the loop would print 1 forever.

    The solution in Swift

    class Solution {
        func printPowers(_ A: Int, _ B: Int) {
            var power = 1
            while power <= B {
                print(power)
                power *= A
            }
        }
    }
    

    Swift details:

    • The underscores in the signature mean the arguments are passed without labels: Solution().printPowers(3, 100).
    • Int is 64 bits. If a power would pass its maximum, power *= A doesn't wrap around quietly: the program traps and crashes. With B near the maximum, the last multiplication could overflow.
    • The method has no return type, so it returns Void, and it only prints.

    Tracing the loop

    For A = 3 and B = 100, the loop moves through these states:

    Checkpower at the checkResult
    11true: print 1, then power becomes 3
    23true: print 3, then power becomes 9
    39true: print 9, then power becomes 27
    427true: print 27, then power becomes 81
    581true: print 81, then power becomes 243
    6243false: the loop ends

    The loop always computes one power beyond the last one printed. That is harmless here, but it is why the overflow caveat above concerns values close to the largest Int.

    Why this is a while loop

    A for loop fits when you know the number of iterations in advance. Here the count depends on the values: it is the number of times you can multiply 1 by A before passing B, which is roughly the logarithm of B in base A. A while loop states the real stopping rule, "keep going while the power fits", so it is the natural choice. The loop runs about the logarithm of B in base A times, far fewer than B, so you don't need to test every number up to B.

    Edge cases and common mistakes

    • B smaller than 1. With B = 0 the condition is false at the start, so nothing is printed. This is correct, since A⁰ = 1 is already greater than 0.
    • B = 1. Only 1 is printed, because the next power, A, is at least 2 when A >= 2.
    • A = 0. The loop prints 1, then power becomes 0 and stays 0, which is always at most B when B is non-negative, so the loop never ends and prints 0 forever. A = 1 loops forever as well, printing 1 each time. Running the loop with these values and a positive B shows an endless stream of output.
    • Printing before the check. Multiplying first and printing afterwards would skip 1 and print a power larger than B.
    • Using < instead of <=. For A = 3 and B = 81, it would leave out 81.

    Testing

    • printPowers(3, 100) prints 1, 3, 9, 27, 81.
    • printPowers(2, 1) prints 1.
    • printPowers(2, 0) prints nothing.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free