Start learning free

LESSON 191 OF 415 · NESTED LOOPS

Print Rhombus in Swift: Building Lines with a Helper

Practice O(n2) Read the full explanation

Given an odd positive integer n print a rhombus of stars as in the example below

Example:

Input: n = 5
Output:
  *  
 *** 
*****
 *** 
  *  

Explanation:
There are n = 5 lines. Each line contains exactly n = 5 characters.
1st line contains two spaces, one '*' and two spaces.
2nd line contains one space, three '*' and one space.
3rd line contains five stars.
4th line contains one space, three '*' and one space.
5th line contains two spaces, one '*' and two spaces.
Note: Be careful to add the necessary spaces at the end of every line!


STEP 1 OF 13
    Ctrl + Enter to check

    SWIFT · NESTED LOOPS

    Print Rhombus in Swift, explained

    Problem overview

    The method printRhombus receives an odd positive integer n and prints a rhombus of stars: n lines, each exactly n characters wide. For n = 5 the output is:

      *  
     *** 
    *****
     *** 
      *  
    

    The first line holds two spaces, one star and two spaces. The stars grow by two per line until the middle line, which is all stars, and then shrink by two per line. The spaces after the last star count: every line must be exactly n characters long.

    Approach: track two counters

    Each line is described by two numbers: how many stars it has, and how many spaces sit on each side. The first line has one star and n / 2 spaces per side. Moving down, each line gains one star on each side of the centre, so stars goes up by 2 and spaces goes down by 1. After the middle line the changes reverse.

    With n = 5, the pairs (spaces, stars) are (2, 1), (1, 3), (0, 5), (1, 3), (2, 1). Notice that spaces * 2 + stars is always n, which is why the line width stays fixed.

    Swift has no built-in "repeat this string" operator, so the lesson writes a small helper, buildString, that appends a one-character string n times. (The standard library does offer String(repeating: " ", count: n), which does the same job.)

    Step by step

    1. Declare stars with var, starting at 1. It changes every line, so it can't be let.
    2. Declare spaces with var, starting at n / 2. Integer division drops the remainder, so for an odd n this is exactly the number of spaces beside the single star.
    3. Loop over 0..<n, one pass per output line. The half-open range excludes n, so the body runs n times.
    4. Build each line as left spaces, stars and right spaces joined with +, then print it. Swift lets a line end in + and continue on the next.
    5. Update the counters after printing. While i < n / 2 the rhombus is still widening. The middle line (i == n / 2) already falls into the else branch, so narrowing starts right after it.
    6. Write the helper signature: buildString(_ n: Int, _ character: String) -> String. The underscores remove the argument labels, so calls read buildString(spaces, " ").
    7. Fill the helper: a var str starts empty, a loop whose variable is _ (it only counts) appends character with +=, and the method returns str.

    The solution in Swift

    class Solution {
    
        func buildString(_ n: Int, _ character: String) -> String {
            var str = ""
            for _ in 0..<n {
                str += character
            }
            return str
        }
    
        func printRhombus(_ n: Int) {
            var stars = 1
            var spaces = n / 2
            for i in 0..<n {
                let line = buildString(spaces, " ") +
                buildString(stars, "*") +
                buildString(spaces, " ")
                print(line)
                if i < n / 2 {
                    stars += 2
                    spaces -= 1
                } else {
                    stars -= 2
                    spaces += 1
                }
            }
        }
    }
    

    Swift details worth knowing:

    • 0..<n versus 0...n. The first excludes n; the second includes it and would print one line too many.
    • for _ in. When the loop variable is unused, _ says so and avoids a warning.
    • Strings are values. str += character changes the local var str only; the caller's string is never touched.
    • Integer division. 5 / 2 is 2 because both operands are Int. With an even n the shape would be off-centre, which is why the problem promises an odd one.
    • Methods call each other by name. Inside Solution, printRhombus calls buildString directly; no self. is needed.

    Why the counters work

    It helps to check the invariant instead of trusting the picture. A line is correct when it is exactly n characters wide, and the width is spaces + stars + spaces. Before the loop, that is n / 2 + 1 + n / 2, which equals n for odd n. Each update adds 2 to one term and removes 1 from each of the other two, so the total never changes. The same argument covers the second half, with the signs swapped.

    The turning point also follows from the numbers. The widest line has n stars and no spaces, and it comes after n / 2 widening steps, that is, on line i = n / 2. After the update on that line the counters would go to n + 2 stars, which can't be printed, so the branch condition must send that line to the shrinking side. That is exactly what i < n / 2 does.

    Walking through n = 5

    Before the loop: stars = 1, spaces = 2. Line 0 prints 2 spaces, 1 star and 2 spaces; the counters become 3 and 1. Line 1 prints 1 space, 3 stars and 1 space; the counters become 5 and 0. Line 2 is five stars and no spaces. Since 2 < 2 is false, the counters go back to 3 and 1, and lines 3 and 4 mirror lines 1 and 0.

    Complexity

    Time: O(n²). There are n lines and each is built from n characters in total, so the program does about n * n character appends.

    Space: O(n). Only one line is held at a time.

    Edge cases and common mistakes

    • n = 1. spaces starts at 0, so one line, a single *, is printed. The counters are updated afterwards but never used again.
    • n = 3. The output is * , *** and * , three lines of three characters.
    • Forgetting the right-hand spaces. The line then ends right after the stars and is shorter than n, so the output no longer matches.
    • Changing direction one line late or early. Using i <= n / 2 would widen the rhombus once more after the middle line. For n = 5 the next line would want 7 stars and -1 spaces, and 0..<-1 is an invalid range in Swift, so the program crashes at run time instead of printing a wrong line.
    • Changing stars by 1. Each side gains a star, so the total changes by 2.

    Testing

    • printRhombus(5) prints the five lines shown above.
    • printRhombus(3) prints * , ***, * .
    • printRhombus(1) prints *.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free