When Patterns Stop Being About Patterns: My Battle With the Spiral (Snail) Matrix

Published: (February 5, 2026 at 11:06 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

1 2 3
8 9 4
7 6 5

Where My Brain Got Stuck

After solving 80+ pattern problems using loops in JavaScript, my brain had been trained (or ruined) to see everything as:

  • math based
  • loop based
  • i and j manipulation
  • stars, numbers, symmetry

Triangles, inverted triangles, pyramids, hourglasses, butterflies, hollow patterns… If it had a name, I probably printed it.

So when this came up, my brain automatically tried to force a mathematical formula out of it. I kept asking questions like:

  • How do I manipulate i and j?
  • Can I tweak loop conditions?
  • Is there some magic equation behind this?

The mistake was that I wasn’t looking at it as rows and columns, as a matrix. I was trying to treat it like a normal pattern problem and it just refused to cooperate.

The Mental Shift That Changed Everything

The breakthrough didn’t come from more loops. It came from changing how I looked at the problem.

This was not a pattern problem. It was a matrix traversal problem disguised as a pattern.
Once I started treating the output as a 2‑D grid, things slowly started making sense. I still couldn’t see the full solution immediately, but at least I had a direction.

Thinking in Boundaries, Not Formulas

Instead of trying to calculate positions, the idea was simple:

  1. Fill the matrix layer by layer.
  2. Move in four directions:
    • left → right
    • top → bottom
    • right → left
    • bottom → top
  3. Shrink the boundaries after each pass.

The variables top, bottom, left, and right define the current layer.

The Code That Finally Worked

let n = 3;

let matrix = Array.from({ length: n }, () => Array(n).fill(0));

let num = 1;

// Boundaries
let top = 0,
    bottom = n - 1;
let left = 0,
    right = n - 1;

while (num = left; i--) {
        matrix[bottom][i] = num++;
    }
    bottom--;

    // bottom → top
    for (let i = bottom; i >= top; i--) {
        matrix[i][left] = num++;
    }
    left++;
}

// Print result
for (let row of matrix) {
    console.log(row.join(' '));
}

What’s Actually Happening Here (Plain English)

  • num increases from 1 to n * n.
  • top, bottom, left, right define the current layer.
  • Each inner loop fills one side of the spiral.
  • After finishing a side, we move the corresponding boundary inward.
  • The while loop stops exactly when the matrix is full.

No formulas, no pattern tricks—just controlled movement.

About That Array.from() Thing

Initially I wrote the matrix values manually. Later I switched to:

let matrix = Array.from({ length: n }, () => Array(n).fill(0));

What it does:

  1. Creates an outer array with n rows.
  2. Each row is a new array of size n.
  3. Fills every cell with 0.

This prevents reference issues (important when you need independent rows) and lets the same logic work for any size, not just 3 × 3.

The Real Lesson (Not the Code)

Sometimes the problem isn’t hard; your mental model is wrong.

I wasn’t failing because I didn’t know loops. I was failing because I forced the problem into a shape it wasn’t. Once I stopped treating it as a pattern and started treating it as a matrix traversal, everything clicked.

Ending This Before I Over‑Explain

I’m still new to this. The question didn’t make me feel smart; it made me feel stuck, then relieved. If you’re struggling with this pattern, you’re not alone. It’s confusing—until it isn’t.

Back to Blog

Related posts

Read more »