I wrote a code that is supposed to generate a spiral pattern of characters. It does generate a spiral, but for some reason, it skips the outermost column, the bottommost row, and the leftmost column (I'll leave an example output below). I can't figure out why this is happening on my own. I do check whether the cell two steps ahead is filled. Only if it is, we should make a turn, essentially creating the spiral.
def asterisk_spiral(size):
matrix = [[' ' for _ in range(size)] for _ in range(size)]
row, col = 0, 0
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
direction = 0
for i in range(1, size * size // 2):
matrix[row][col] = '*'
next_row, next_col = row + directions[direction][0], col + directions[direction][1]
next_next_row, next_next_col = row + 2 * directions[direction][0], col + 2 * directions[direction][1]
if (
0 <= next_row < size
and 0 <= next_col < size
and 0 <= next_next_row < size
and 0 <= next_next_col < size
and matrix[next_row][next_col] == ' '
and matrix[next_next_row][next_next_col] != '*'
):
row, col = next_row, next_col
else:
# turn
direction = (direction + 1) % 4
row, col = row + directions[direction][0], col + directions[direction][1]
return matrix
def print_spiral(matrix):
for row in matrix:
print(' '.join(row))
size = 9
spiral_matrix = asterisk_spiral(size)
print_spiral(spiral_matrix)
Result:
[['*', '*', '*', '*', '*', '*', '*', '*', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' '],
[' ', '*', '*', '*', '*', '*', ' ', '*', ' '],
[' ', '*', ' ', ' ', ' ', '*', ' ', '*', ' '],
[' ', '*', ' ', '*', '*', '*', ' ', '*', ' '],
[' ', '*', ' ', '*', '*', '*', ' ', '*', ' '],
[' ', '*', ' ', ' ', ' ', ' ', ' ', '*', ' '],
[' ', '*', '*', '*', '*', '*', '*', '*', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']]
whereas expected matrix is:
[['*', '*', '*', '*', '*', '*', '*', '*', '*'],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
['*', '*', '*', '*', '*', '*', '*', ' ', '*'],
['*', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*'],
['*', ' ', '*', '*', '*', ' ', '*', ' ', '*'],
['*', ' ', '*', ' ', ' ', ' ', '*', ' ', '*'],
['*', ' ', '*', '*', '*', '*', '*', ' ', '*'],
['*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
['*', '*', '*', '*', '*', '*', '*', '*', '*']]
When the
ifcondition0 <= next_row < sizeis true, but0 <= next_next_row < sizeis not true, your logic will trigger a turn, but that means that for the first few lines the turn is made before hitting the boundary of the square, i.e. one step too early.Instead you should have this logic:
"When the next cell in the current direction exists, and it is not so that one step further there is an asterisk, then go on in the same direction".
That means the
ifcondition could look like this:Once you have corrected this, you'll notice another issue: the loop doesn't make enough iterations. The
forstatement should be corrected to this:Depending how you want the output to look for when
sizeis an even number, you may want to reduce that by one iteration. If so, change it to this:Choose whichever of the two suits your needs for the case where
sizeis even.