This is not a homework assignment, just me preparing for my final programming exam. We were introduced this problem just to think, not to solve, but I would like to know how to deal with this type of problems (using matrices to draw specific patterns).
I'm asked to write a program that prints “spirals” of size n × n. Input consists of a sequence of strictly positive natural numbers, ended with zero. And, for each n, I must print a spiral of size n × n. Note that in the bottom row and in the right column there are only ‘X’s. Also, I need to print an empty line after each spiral.
This is an Input/Output example:
Input:
4
6
7
0
Output:
.XXX
.X.X
...X
XXXX
.XXXXX
.X...X
.X.X.X
.XXX.X
.....X
XXXXXX
.XXXXXX
.X....X
.X.XX.X
.X..X.X
.XXXX.X
......X
XXXXXXX
I'm stuck at this point, I printed bottom and right 'X' lines since they will always be there. Then, I tried to make iterations to draw each 'L' of the spiral. So, first an L was entered (bottom right). Then, an inverse L, etc.
This is my code till now:
import sys
def spirals(n):
M = [['.' for _ in range(n)] for _ in range(n)]
for row in range(n):
M[row][n-1] = 'X'
for col in range(n):
M[n-1][col] = 'X'
spirals_rec(M, 0, n-1)
return M
def spirals_rec(M, i, j):
for _ in range(n//2):
pos = 1
while pos < j:
M[i][pos] = 'X'
pos += 1
prev1_pos = pos
pos = 1
while pos < j-1:
M[pos][i+1] = 'X'
pos += 1
prev2_pos = pos
i = prev2_pos-1
j = prev1_pos-1
n = int(sys.stdin.readline())
for row in spirals(n):
print(row)
I'm just trying to make it work for a single integer input. Then, I will adjust to the statement requirements. This is what my code returns, given the example input:
.XXX
.X.X
...X
XXXX
.XXXXX
.X.XXX
.XX.XX
.XXX.X
.....X
XXXXXX
.XXXXXX
.X..XXX
.X..XXX
.XXX.XX
.XXXX.X
......X
XXXXXXX
I have not been taught to solve this type of problems, but I heard my professor puts this type of exercises for exams. With this post I would like to obtain some ideas on how I have to solve this, if I'm on the correct way or I should reformulate all again. I just can use import sys (to read input, in this case, and integer), not other packages.
I appreciate any comment or ideas. Thanks.
I forgot to add this observation of the statement: A matrix is not needed to solve this problem, but use it for simplicity.
I think for me, a matrix would be indeed easier. However, if there is any other easier way of solving this, I'll be grateful of reading it.
This problem repeats itself after every four edges have been drawn. For example, in the spiral below for n=9
, you can clearly see the n=5
spiral (which I've modified to have Os instead of Xs, for contrast), set in from the edges of the grid by two spaces, and the n=1
"spiral" drawn with a single X at the very center, offset by four spaces from the outside of the grid:
. X X X X X X X X
. X . . . . . . X
. X . O O O O . X
. X . O . . O . X
. X . O X . O . X
. X . . . . O . X
. X O O O O O . X
. . . . . . . . X
X X X X X X X X X
So I'd write code that draws four sides of one loop of a spiral, and which can handle being offset into a larger matrix. Make sure you fail safe for small sizes where you don't actually need all four of the sides!
Here's my code, that loops over the offset into the grid:
def spiral(n):
M = [['.' for _ in range(n)] for _ in range(n)]
for offset in range(0, (n+1)//2, 2):
for i in range(offset, n-offset): # bottom side
M[n-offset-1][i] = 'X'
for i in range(offset, n-offset-1): # right side
M[i][n-offset-1] = 'X'
for i in range(offset+1, n-offset-1): # top side
M[offset][i] = 'X'
for i in range(offset+1, n-offset-2): # left side
M[i][offset+1] = 'X'
return M
Because a range
that has reversed or overlapping end points is "empty" but still iterable, this code handles the inner parts of the spiral that don't need all four sides without needing any explicit special cases (some of the loops just won't do anything).