Start learning free

LESSON 179 OF 348 · FUNCTIONS & CLASSES

Print X in TypeScript: Building Each Line with 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

    TYPESCRIPT · FUNCTIONS & CLASSES

    Print X in TypeScript, explained

    Problem overview

    The method printX receives a positive integer n and prints an n by n picture of the letter X. Every line has exactly n characters. Each character is x if it lies on one of the two diagonals and - otherwise. The method prints the lines with console.log and returns nothing.

    For n = 5 the output is:

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

    The first line has its x's at the two ends, positions 0 and 4. Each following line has them one step closer to the middle. On the third line the two positions meet at 2, so that line holds a single x.

    Approach: track two column positions

    You don't need to search the grid for diagonal cells. On line i (counting from 0), the main diagonal crosses column i and the other diagonal crosses column n - 1 - i. So every line is fully described by two numbers, and those numbers change in a simple way from one line to the next: the first goes up by 1 and the second goes down by 1.

    That suggests two variables, firstX and secondX, starting at 0 and n - 1. The program prints one line, then moves both variables one step inward. Building a single line from those two numbers is a separate small job, so the lesson puts it in its own helper, buildString.

    Step by step

    1. Declare the two positions. Both are numbers declared on one line. They start at the two ends of the first line.
    2. Loop once per line. A for loop with an index i from 0 while i < n gives exactly n lines. The index is not used inside the loop body, because the two position variables carry all the information.
    3. Build and print the line. Pretend buildString already exists. It takes n and the two positions and returns the line as a string. Inside a class, a method is reached through this, so the call is this.buildString(...).
    4. Move the x's inward. After printing, firstX goes up by 1 and secondX goes down by 1, ready for the next line.
    5. Write the helper's signature. It sits in the same class and matches the call: three number parameters and a string return type.
    6. Start with an empty string. The helper collects the characters of one line in str.
    7. Loop over the columns. Another for loop runs from 0 while i < n, one iteration per character.
    8. Choose the character. If i equals firstX or secondX, append "x". Otherwise append "-".
    9. Return after the loop. Returning inside the loop would stop after the first character.

    The solution in TypeScript

    class Solution {
        printX(n: number): void {
            let firstX: number = 0, secondX: number = n - 1;
            for (let i: number = 0; i < n; i++) {
                const str: string = this.buildString(n, firstX, secondX);
                console.log(str);
                firstX++;
                secondX--;
            }
        }
    
        buildString(n: number, firstX: number, secondX: number): string {
            let str: string = '';
            for (let i: number = 0; i < n; i++) {
                if (i === firstX || i === secondX) {
                    str += "x";
                } else {
                    str += "-";
                }
            }
            return str;
        }
    }
    

    Some TypeScript details in this code:

    • The annotations are documentation for the compiler. let firstX: number would work the same without : number, because TypeScript infers the type from the initial value. The annotations disappear when the code is compiled to JavaScript.
    • One let, two variables. let firstX: number = 0, secondX: number = n - 1; declares both, and each one carries its own annotation.
    • const for str in printX. The line is never reassigned, so const fits. In buildString, str grows with +=, so it must be let.
    • ===. Strict equality compares without converting types. For numbers it is the right default.
    • Strings are immutable. str += "x" creates a new string and stores it back in str. For a line of a few dozen characters that is fine.
    • this. is required. A bare buildString(...) inside a method looks for a variable or function of that name, not a method of the class.

    Complexity

    Time: O(n²). printX runs n iterations, and each calls buildString, which does n iterations of its own. The output itself has n * n characters, so no approach that prints them all can do better.

    Space: O(n). Only one line is held in memory at a time, and the previous line is discarded when the next one is built.

    Edge cases and common mistakes

    • n = 1. Both positions are 0, so the output is the single line x.
    • Even n. For n = 4 the x's never meet at one column: the middle two lines each have the x's at positions 1 and 2, so they look like -xx-. The output is:
    x--x
    -xx-
    -xx-
    x--x
    
    • Odd n. On the middle line the two positions are equal, so the condition matches once and the line has one x.
    • Starting at 1 and n. Positions in the string are counted from 0. Starting firstX at 1 and secondX at n pushes the picture one column to the right, and secondX would never match.
    • Moving the positions before printing. The first line would already be shifted inward, and the picture would be wrong from the top.
    • Forgetting to move one of the variables. If secondX stayed at n - 1, the right-hand x would stay on the last column on every line.
    • Printing characters one at a time. console.log always ends the line it prints. To print a whole line you have to build the string first, which is what the helper does.

    Testing

    • n = 5 prints the picture at the top.
    • n = 4 prints the four lines above.
    • n = 1 prints x.
    • n = 2 prints xx twice, because both positions fill the two columns.
    • Calling buildString(5, 1, 3) returns -x-x-.
    Keep going with TypeScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free