Start learning free

LESSON 178 OF 347 · FUNCTIONS & CLASSES

Print X in C#: Drawing a Diagonal Pattern with Loops

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

    C# · FUNCTIONS & CLASSES

    Print X in C#, explained

    Problem overview

    The task is to write the method PrintX(int n), which prints an n by n grid of characters. Every position holds - except the two diagonals, which hold x, so together the x characters form the letter X.

    For n = 5 the output is:

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

    Each line has exactly n characters. On line 0 the x characters are at positions 0 and 4. On line 1 they are at positions 1 and 3. On line 2 both diagonals meet at position 2, so that line has a single x. After the middle, the x characters move apart again.

    Approach: one line at a time

    You could think of the grid as a two-dimensional array and fill it cell by cell, but there is a simpler view. The output is just a list of lines, and each line is fully described by two numbers: the positions of its two x characters.

    On the first line those positions are 0 and n - 1, the two ends. On every following line the left x moves one position right and the right x moves one position left. The diagonals cross in the middle and keep going, so the numbers simply carry on changing by one per line. Two counters, firstX and secondX, are all the state the program needs.

    Splitting the work into two methods keeps each one short. PrintX handles the vertical direction: it loops over the lines and moves the counters. A helper, BuildString, handles the horizontal direction: given the two positions, it builds one line of text. The helper has no side effects, so you can reason about it separately.

    Step by step

    1. Declare the two counters in one statement: firstX starts at 0 and secondX at n - 1, the two ends of the first line.
    2. Loop once per line. A for loop with i from 0 while i < n runs the body n times, because the grid has n lines.
    3. Call the helper inside the loop and keep its result in a string named str. At this point the helper doesn't exist yet. Writing the call first lets you decide what the helper must accept and return before you write it. Then print the string with Console.WriteLine, which adds the line break.
    4. Move the counters after printing: firstX goes up by one and secondX goes down by one, ready for the next line.
    5. Write the helper's signature to match the call: public string BuildString(int n, int firstX, int secondX). A method in the same class can be called by its plain name, with no object in front.
    6. Start with an empty string named str that will collect the characters.
    7. Loop over character positions with another for loop from 0 while i < n.
    8. Choose the character. If i equals firstX or secondX, append "x"; otherwise append "-". The || operator is true when at least one side is true.
    9. Return the string after the loop ends, once every position has a character.

    The solution in C#

    class Solution {
    
        public string BuildString(int n, int firstX, int secondX) {
            string str = "";
            for (int i = 0; i < n; i++) {
                if (i == firstX || i == secondX) {
                    str += "x";
                } else {
                    str += "-";
                }
            }
            return str;
        }
    
        public void PrintX(int n) {
            int firstX = 0, secondX = n - 1;
            for (int i = 0; i < n; i++) {
                string str = BuildString(n, firstX, secondX);
                Console.WriteLine(str);
                firstX++;
                secondX--;
            }
        }
    }
    

    A few C# details are worth knowing:

    • Several variables in one declaration. int firstX = 0, secondX = n - 1; declares two int variables, each with its own initial value. The second one may even use a parameter, as it does here.
    • Strings are immutable. str += "x" doesn't change the existing string. It creates a new, longer string and assigns it to str. That is fine for short lines, and the complexity section shows its cost.
    • Double quotes for strings. "x" is a string of one character. The single-quoted 'x' is a char. For += on a string, either one works, but this solution uses strings throughout.
    • || short-circuits. If i == firstX is already true, C# doesn't evaluate the second comparison.
    • WriteLine versus Write. Console.WriteLine ends the output with a line break, which is what separates the lines of the picture. Console.Write would run them together.

    Complexity

    The output has n * n characters, so no solution can beat O(n²) time. This one is slightly slower. Each += copies the string built so far, so building one line of length n copies about 1 + 2 + ... + n characters, which is O(n²) work. Doing that for n lines gives O(n³) in total. For the sizes in this lesson that is invisible.

    The extra space is O(n): only one line exists at a time, and old intermediate strings become garbage that .NET collects.

    If you wanted an O(n²) version, you would build each line with new string('-', n) and a char[], or with StringBuilder, which appends in place. For this lesson, the string version is clearer.

    Edge cases and common mistakes

    • Even n. The diagonals never share a cell, so there is no single-x line. For n = 4 the output is x--x, -xx-, -xx-, x--x. The counters pass each other after the middle, and the code handles that without a special case.
    • n = 1. Both counters start at 0, so the only line is x.
    • n = 2. Both lines are xx.
    • Odd n. On the middle line the counters are equal, so the same position matches twice and one x appears.
    • Moving the counters before printing. Then the first line would already be shifted. Update them after the line is printed.
    • Using <= in a loop. i <= n produces n + 1 lines or characters. Positions run from 0 to n - 1.
    • Using && instead of ||. A position can't be both counters at once except in the middle, so the grid would contain almost no x characters.
    • Returning inside the loop. A return placed before the loop closes ends the helper after one character.

    Testing

    • PrintX(1) prints x.
    • PrintX(2) prints xx twice.
    • PrintX(3) prints x-x, -x-, x-x.
    • PrintX(5) prints the grid from the example.
    • BuildString(5, 1, 3) returns -x-x-.
    • PrintX(0) prints nothing, because the loop never runs.
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free