# Making an array of spiral numbers

## Context

I was solving a task on CodeSignal here

I have also put the task at the bottom of the post.

## Code

def check(matrix, num):
for arr in matrix:
for number in arr:
if number != num:
return True
return False

def spiralNumbers(n):
array = []
array_dup = []
for i in range(n):
arr1 = []
for j in range(n):
arr1.append(j)
array.append(arr1)

for i in range(n):
arr1 = []
for j in range(n):
arr1.append(j)
array_dup.append(arr1)

selected_row, selected_num_pos = 0, -1
count = 1
run = True
while run:
its_neg = False
for i in range(selected_num_pos+1, n):
if array_dup[selected_row][i] == -1:
its_neg = True
break
array[selected_row][i] = count
array_dup[selected_row][i] = -1
count += 1
if its_neg:
selected_num_pos = i-1
else:
selected_num_pos = i

its_neg = False
for i in range(selected_row+1, n):
if array_dup[i][selected_num_pos] == -1:
its_neg = True
break
array[i][selected_num_pos] = count
array_dup[i][selected_num_pos] = -1
count += 1
if its_neg:
selected_row = i-1
else:
selected_row = i

its_neg = False
for i in range(selected_num_pos-1, -1, -1):
if array_dup[selected_row][i] == -1:
its_neg = True
break
array[selected_row][i] = count
array_dup[selected_row][i] = -1
count += 1
if its_neg:
selected_num_pos = i+1
else:
selected_num_pos = i

its_neg = False
for i in range(selected_row-1, -1, -1):
if array_dup[i][selected_num_pos] == -1:
its_neg = True
break
array[i][selected_num_pos] = count
array_dup[i][selected_num_pos] = -1
count += 1
if its_neg:
selected_row = i+1
else:
selected_row = i

run = check(array_dup, -1)

return array


## Question

The Code I wrote works without any error and returns the expected output, but the code seems a bit long for this problem. I wanted to know how can I make this code shorter and more efficient?

• Are there no lower/upper limits for N? Oct 24, 2020 at 16:09
• An outline describing your method would be helpful. Oct 24, 2020 at 16:14

• You're using non-standard names. Usual names are A for the matrix, i for the row index, and j for the column index.
• List repetition and comprehension make the initialization shorter and faster.
• Using deltas for the four directions can avoid quadrupling code.
• You can know when to change direction by checking whether the next element in the current direction is already set.
• Your check is inefficient. Instead of searching the matrix for an unset spot, just do while count <= n**2:. Or, try to loop through the range of numbers.
• Your current code crashes for n = 0 because it always enters the loop, as you compute run only at the end. With while count <= n**2: you'd succeed.
def spiralNumbers(n):
A = [[0] * n for _ in range(n)]
i = j = di = 0
dj = 1
for A[i][j] in range(1, n**2 + 1):
if A[(i+di) % n][(j+dj) % n]:
di, dj = dj, -di
i += di
j += dj
return A


The % n is just a little trick to avoid checking for index-out-of-bounds.