Start learning free

LESSON 179 OF 348 · FUNCTIONS & CLASSES

Print X in Kotlin: Building Each Line with Two Moving Indices

Practice O(n2) Read the full explanation

Given a positive integer n print matrix containing an X as in the example below

Example:

Input: n = 5
Output:
x---x
-x-x-
--x--
-x-x-
x---x
Explanation:
Each line contains exactly n = 5 characters and two 'x's.
Each diagonal contains 'x'

Hints:

Notice that on each line there will be exactly two x and the other characters are all -. The only exception is the middle line which will have only one x. How can we use this info?

We can print the matrix line by line. For each line we need to know the two columns where we should print x. How can we know these two columns for every line?

We'll store the columns' indices in two variables firstX and secondX, initially equal to 1 and n respectively for the first line.
How should these variables change from line to line?

firstX should get incremented and secondX should get decremented.
Now for each line, you now the 'special' columns. How will you print that line?

We'll use a for loop to iterate through every column index from 1 to n.
What should we do inside the loop?

We should use an if - else statement and check if the current index is firstX or secondX and if so, print x. Otherwise, print -.
STEP 1 OF 10
    Ctrl + Enter to check

    KOTLIN · FUNCTIONS & CLASSES

    Print X in Kotlin, explained

    Problem overview

    The function printX(n: Int) prints an n by n picture of the letter X. Each line has n characters: x where the two diagonals cross that line, and - everywhere else. The function prints the lines with println and returns nothing.

    For n = 5 the output is:

    x---x
    -x-x-
    --x--
    -x-x-
    x---x
    

    The first line has its x characters at positions 0 and 4, the second at 1 and 3, and the middle line at position 2 twice, which shows as a single x. For an even n such as 4 the diagonals cross between two columns, so the two middle lines both read -xx-.

    Approach: two positions that walk toward each other

    Think of the picture one line at a time. On line 0 the x characters sit at the two ends, positions 0 and n - 1. On every later line the left one moves one step right and the right one moves one step left. So two variables, firstX and secondX, are enough to describe every line.

    Printing a line then means walking over the positions 0 to n - 1, writing x at a position equal to firstX or secondX and - at any other. Splitting the work into a function that prints and a helper that builds one line keeps each part short.

    Step by step

    1. Declare the two positions with var. firstX starts at 0 and secondX at n - 1. They change on every line, so val would not work.
    2. Loop once per line with for (i in 0 until n). The loop counts lines and its index is not used inside.
    3. Build and print the line. The loop calls a helper, buildString(n, firstX, secondX), stores the result in a val named str and prints it. Writing the call first, and the helper afterwards, lets you think about one problem at a time. Order of members inside a class does not matter in Kotlin.
    4. Move the positions. After printing, firstX++ and secondX-- prepare the next line.
    5. Write the helper's header. It takes three Int parameters and returns a String. In Kotlin the return type goes after the parameter list, following a colon.
    6. Start from an empty string held in a var, because each += replaces it with a longer string.
    7. Loop over the columns with another 0 until n.
    8. Append "x" when i == firstX || i == secondX.
    9. Append "-" in the else branch.
    10. Return the string after the loop, once every position is filled.

    The solution in Kotlin

    class Solution {
    
        fun printX(n: Int) {
            var firstX = 0
            var secondX = n - 1
            for (i in 0 until n) {
                val str = buildString(n, firstX, secondX)
                println(str)
                firstX++
                secondX--
            }
        }
    
        fun buildString(n: Int, firstX: Int, secondX: Int): String {
            var str = ""
            for (i in 0 until n) {
                if (i == firstX || i == secondX) {
                    str += "x"
                } else {
                    str += "-"
                }
            }
            return str
        }
    }
    

    Kotlin details worth knowing:

    • 0 until n excludes n. It produces 0, 1, ..., n - 1, exactly the positions of a line. 0..n would include n and print one character too many.
    • Two variables called str. The one in printX is a read-only val; the one in buildString is a var. They live in different functions and do not interact.
    • Parameters are read-only. firstX and secondX inside buildString cannot be reassigned. That is why the changing copies live in printX as var.
    • += on a String creates a new string. Strings never change in place, so the helper copies the line so far at each step. For one line that costs O(n²) work in total, which is fine for the sizes here.
    • || short-circuits. If i == firstX is true, the second comparison is skipped.

    Tracing n = 5

    The loop runs five times. The pairs (firstX, secondX) passed to the helper are (0, 4), (1, 3), (2, 2), (3, 1) and (4, 0). In the third pair both positions are 2, so the helper appends a single x at position 2 and the line is --x--. In the fourth and fifth pairs the positions have crossed, and since the test is symmetric, the lines -x-x- and x---x come out the same as the second and first.

    Complexity

    The function prints n lines of n characters each, so it does at least O(n²) work, which is the size of its own output. Building each line with += adds a factor of up to n for the copying, giving O(n³) in the worst case for this implementation. The only extra memory is the current line.

    Edge cases and common mistakes

    • n = 1. Both positions are 0, so the single line is x.
    • Even n. For n = 4 the output is x--x, -xx-, -xx-, x--x. The positions never coincide, they pass each other, and the second half of the picture mirrors the first. For n = 2 both lines read xx.
    • Forgetting to move the positions. Without firstX++ and secondX-- every line would look like the first one.
    • Moving them before printing. The first line would be missing its edge x characters.
    • Using 0..n. The extra iteration adds a character to each line and an extra line to the output.
    • Declaring the positions with val. firstX++ then fails to compile because a val cannot be reassigned.
    • Returning instead of printing. printX returns nothing; its result is what it writes with println.

    Testing

    • n = 1 prints x.
    • n = 2 prints xx twice.
    • n = 4 prints x--x, -xx-, -xx-, x--x, one per line.
    • n = 5 prints the picture from the overview.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free