Start learning free

LESSON 179 OF 338 · FUNCTIONS & CLASSES

Print X in Go: Two Moving Columns and a Helper

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 9
    Ctrl + Enter to check

    GO · FUNCTIONS & CLASSES

    Print X in Go, explained

    Problem overview

    The function printX receives a positive integer n and prints an n by n grid made of - characters with an X drawn in x characters along the two diagonals. For n = 5:

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

    Each line has two x characters, except the middle line of an odd-sized grid, where the two diagonals meet and one x remains.

    Approach

    The grid is easiest to think about one line at a time. On line i (counting from 0), the main diagonal puts an x in column i, and the other diagonal puts one in column n - 1 - i. Every other column holds -.

    Rather than compute n - 1 - i each time, the lesson keeps the two columns in variables, firstX and secondX. They start at the two ends of the first line, 0 and n - 1, and move one step toward each other after every line. When they meet, as they do in the middle of an odd grid, both point at the same column, and the check simply finds one match, so a single x is printed. This needs no special case.

    The work splits in two: printX walks over the lines, and the helper buildString creates one line from n and the two columns.

    On n = 5 the pair of columns goes (0, 4), (1, 3), (2, 2), (3, 1), (4, 0). After the middle line the pair simply passes through itself: the first column is now larger than the second, but the check does not care about their order. Both diagonals keep drawing their x in the right place, so the bottom half mirrors the top half with no extra code.

    Printing the grid line by line, with one string per line, matches how the output is read: each fmt.Println call produces one finished line of exactly n characters.

    Step by step

    printX

    1. Declare firstX as 0 and secondX as n - 1.
    2. Loop i from 0 while i < n, one pass per line.
    3. Call buildString(n, firstX, secondX), store the result in str and print it with fmt.Println.
    4. Add 1 to firstX and subtract 1 from secondX for the next line.

    buildString

    1. Declare it with three int parameters (n, firstX, secondX) and a string result, after the other function.
    2. Start str as an empty string.
    3. Loop i from 0 while i < n, one pass per column.
    4. If i equals firstX or secondX, append "x". Otherwise append "-".
    5. Return str once the loop is done.

    Take the second line of the example, where firstX is 1 and secondX is 3. The helper visits columns 0 to 4: column 0 is neither, so it adds -. Column 1 matches firstX, so x. Column 2 is -, column 3 matches secondX and gives x, and column 4 is -. The result is -x-x-, as expected.

    An equivalent design drops the two variables and tests i == row || i == n - 1 - row inside the loop. It gives the same output. The lesson's version splits the line-building into a helper that takes the columns as plain arguments, so it can be reasoned about on its own.

    The solution in Go

    func printX(n int) {
        firstX := 0
        secondX := n - 1
        for i := 0; i < n; i++ {
            str := buildString(n, firstX, secondX)
            fmt.Println(str)
            firstX += 1
            secondX -= 1
        }
    }
    
    func buildString(n int, firstX int, secondX int) string {
        str := ""
        for i := 0; i < n; i++ {
            if i == firstX || i == secondX {
                str += "x"
            } else {
                str += "-"
            }
        }
        return str
    }
    

    Language details worth knowing

    Both functions use a loop variable called i and a parameter called n. Go gives each function its own scope, so they don't interfere. In printX, i counts lines. In buildString, it counts columns.

    The condition i == firstX || i == secondX uses ||, which is true when at least one side is true. When both columns are equal, the condition is true once and the character is added once, which is why the middle line has a single x.

    Go's += and -= work like in other languages. You could also write firstX++ and secondX--, but these are statements and can't be used inside expressions.

    The result type goes after the parameter list in the function header: func buildString(...) string. Parameters of the same type can be grouped, as in n, firstX, secondX int. The lesson spells out each type, which is equally valid.

    Complexity

    There are n lines, each built in O(n) time, so the time is O(n²), which is also the size of the output. Extra space is O(n) for the line being built.

    Edge cases and common mistakes

    • n = 1 prints a single x: both columns are 0.
    • For an even n, the columns never coincide. They cross between two lines, and the two middle lines are both -xx- when n = 4.
    • Starting secondX at n instead of n - 1 shifts the second diagonal off the grid, because columns here start at 0.
    • Forgetting to update firstX and secondX after each line prints the same line n times.
    • Using && instead of || would put an x only where both columns coincide, in the middle.

    Testing

    For n = 3 the output should be:

    x-x
    -x-
    x-x
    

    For n = 1 it is a single x, and for n = 4:

    x--x
    -xx-
    -xx-
    x--x
    
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free