8
\$\begingroup\$

Context

I was solving a task on CodeSignal here

You can view the task on the link I provided above.

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?

The Task

enter image description here

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

1 Answer 1

5
\$\begingroup\$
  • 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.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.