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
- Declare
firstXas 0 andsecondXasn - 1. - Loop
ifrom 0 whilei < n, one pass per line. - Call
buildString(n, firstX, secondX), store the result instrand print it withfmt.Println. - Add 1 to
firstXand subtract 1 fromsecondXfor the next line.
buildString
- Declare it with three
intparameters (n,firstX,secondX) and astringresult, after the other function. - Start
stras an empty string. - Loop
ifrom 0 whilei < n, one pass per column. - If
iequalsfirstXorsecondX, append"x". Otherwise append"-". - Return
stronce 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 = 1prints a singlex: 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-whenn = 4. - Starting
secondXatninstead ofn - 1shifts the second diagonal off the grid, because columns here start at 0. - Forgetting to update
firstXandsecondXafter each line prints the same linentimes. - Using
&&instead of||would put anxonly 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