PHP Perfect Square Spiral Pattern

Intermediate
6 min read
Updated: Sep 2026
3 programs
Live preview

What Is This Pattern?

A perfect square spiral fills an n×n grid with 1..n² in clockwise rings — top → right → bottom → left — then shrinks inward until every cell is filled.

Remember
Rule: for each layer (low..high)
        fill top row, right col, bottom row, left col
        then low++, high--

   1   2   3   4   5
  16  17  18  19   6
  15  24  25  20   7
  14  23  22  21   8
  13  12  11  10   9     ← n = 5

Unlike Program 61 (1D digit reverse), here you allocate a 2D array and control four edge loops per ring. This closes the PHP number-pattern series — next, explore star patterns.

How to Solve It

Allocate an n×n array. For each ring marked by $low/$high, fill four sides in order, then tighten the boundaries. Print with printf("%4d", …) and echo PHP_EOL.

MethodIdeaBest for
Fixed 10×10Hard-code size; inline four edge loopsLabs and demos
CLI sizeSame fill; read $n at runtimeAny square size
Helper functionsfill_spiral + print_matrixCleaner structure

Pseudocode

Pseudocode
allocate a[n][n]
low = 0, high = n - 1, val = 1

for layer from 0 to ceil(n/2) - 1:
    for j from low to high:          // top
        a[low][j] = val; val++
    for i from low+1 to high:        // right
        a[i][high] = val; val++
    for j from high-1 down to low:   // bottom
        a[high][j] = val; val++
    for i from high-1 down to low+1: // left
        a[i][low] = val; val++
    low++; high--

print matrix with fixed-width cells

Cheat sheet

GoalPattern
Allocate grid$a = array_fill(0, $n, array_fill(0, $n, 0));
Boundaries$low = 0; $high = $n - 1;
Layer count(int)(($n + 1) / 2) rings
Fill orderTop → right → bottom → left
Print cellprintf("%4d", $a[$i][$j]);
End the rowecho PHP_EOL;

Printing Numbers vs Starting a New Line

APIEffectUse for
printf("%4d", …)Stays on the same lineEach aligned cell
echo PHP_EOLEnds the current lineAfter a full matrix row

Print all cells in a row, then break once.

Live Preview

Change the matrix size and the spiral updates instantly.

Whole numbers from 3 to 10. Tap a chip or type a value — the preview redraws as you go.

Live result n = 5 · cells = 25
   1   2   3   4   5
  16  17  18  19   6
  15  24  25  20   7
  14  23  22  21   8
  13  12  11  10   9

Worked Walkthrough

Trace the outer ring of a 4×4 spiral — values 1..12 on the border, then the inner 2×2 fills 13..16.

SideLoopValues
Top$j = 0..3 on row 01 2 3 4
Right$i = 1..3 on col 35 6 7
Bottom$j = 2..0 on row 38 9 10
Left$i = 2..1 on col 011 12

Then $low = 1, $high = 2 fills the center: 13 14 / 16 15. Corners are written once — that is why right starts at $low + 1 and left stops before $low.

PHP Programs

Three complete programs: fixed 10×10, CLI size, and a fill_spiral helper. Use View Output for sample results.

Example 1 — Fixed $n = 10

Hard-coded 10×10 — four edge loops per layer with $low and $high.

PHP
<?php
$n = 10;
$a = array_fill(0, $n, array_fill(0, $n, 0));
$low = 0;
$high = $n - 1;
$val = 1;

for ($layer = 0; $layer < (int)(($n + 1) / 2); $layer++, $low++, $high--) {
    for ($j = $low; $j <= $high; $j++, $val++) $a[$low][$j] = $val;
    for ($i = $low + 1; $i <= $high; $i++, $val++) $a[$i][$high] = $val;
    for ($j = $high - 1; $j >= $low; $j--, $val++) $a[$high][$j] = $val;
    for ($i = $high - 1; $i > $low; $i--, $val++) $a[$i][$low] = $val;
}

echo "Perfect Square Spiral" . PHP_EOL;
for ($i = 0; $i < $n; $i++) {
    for ($j = 0; $j < $n; $j++)
        printf("%4d", $a[$i][$j]);
    echo PHP_EOL;
}
?>

How It Works

1. Allocate. array_fill builds an empty 10×10 grid before any values are written.

2. Fill rings. Each layer writes top, right, bottom, left, then $low++ / $high-- moves inward.

3. Print aligned. printf("%4d", …) keeps columns lined up through 100.

Example 2 — User Input Size

Read $n from the CLI and fill an n×n spiral.

PHP
<?php
echo "Enter matrix size n: ";
$input = trim(fgets(STDIN));
if (!is_numeric($input) || (int) $input <= 0) {
    echo "Please enter a positive integer." . PHP_EOL;
    exit(1);
}
$n = (int) $input;

$a = array_fill(0, $n, array_fill(0, $n, 0));
$low = 0;
$high = $n - 1;
$val = 1;

for ($layer = 0; $layer < (int)(($n + 1) / 2); $layer++, $low++, $high--) {
    for ($j = $low; $j <= $high; $j++, $val++) $a[$low][$j] = $val;
    for ($i = $low + 1; $i <= $high; $i++, $val++) $a[$i][$high] = $val;
    for ($j = $high - 1; $j >= $low; $j--, $val++) $a[$high][$j] = $val;
    for ($i = $high - 1; $i > $low; $i--, $val++) $a[$i][$low] = $val;
}

for ($i = 0; $i < $n; $i++) {
    for ($j = 0; $j < $n; $j++)
        printf("%4d", $a[$i][$j]);
    echo PHP_EOL;
}
?>

How It Works

1. Validate input. is_numeric rejects letters; require a positive size.

2. Same fill. Edge loops match Example 1 — only the source of $n changes.

3. Scale. For $n = 5, the center cell is 25 (odd n).

Example 3 — fill_spiral Helper

Refactor layer logic into fill_spiral and print with print_matrix.

PHP
<?php
function fill_spiral(&$a, $n) {
    $low = 0;
    $high = $n - 1;
    $val = 1;
    for ($layer = 0; $layer < (int)(($n + 1) / 2); $layer++, $low++, $high--) {
        for ($j = $low; $j <= $high; $j++, $val++) $a[$low][$j] = $val;
        for ($i = $low + 1; $i <= $high; $i++, $val++) $a[$i][$high] = $val;
        for ($j = $high - 1; $j >= $low; $j--, $val++) $a[$high][$j] = $val;
        for ($i = $high - 1; $i > $low; $i--, $val++) $a[$i][$low] = $val;
    }
}

function print_matrix($a, $n) {
    for ($i = 0; $i < $n; $i++) {
        for ($j = 0; $j < $n; $j++)
            printf("%4d", $a[$i][$j]);
        echo PHP_EOL;
    }
}

$n = 10;
$a = array_fill(0, $n, array_fill(0, $n, 0));
fill_spiral($a, $n);
print_matrix($a, $n);
?>

How It Works

1. Pass by reference. fill_spiral(&$a, $n) writes into the same array the caller allocated.

2. Same edges. Top → right → bottom → left logic is unchanged — only packaged in a function.

3. Separate print. print_matrix keeps formatting out of the fill routine.

Edge Cases & Pitfalls

Check these before calling the solution done.

double corner

Starting every side at the same corner

That overwrites cells. Keep right at $low + 1, bottom to $low, left down to $low + 1.

wrong shrink

Forgetting to update $low / $high

Without $low++ and $high--, the outer ring repeats forever or overlaps.

PHP_EOL inside

echo PHP_EOL inside the cell loop

That prints one number per line. Call it only after each matrix row finishes.

n = 1

Single cell

Output is just 1 — one layer, top loop only.

n ≤ 0

Invalid size

Reject with a clear message before allocating the array.

narrow pad

Using %3d for large n

When n² ≥ 1000, widen the format (e.g. %5d) so columns stay aligned.

Time and Space Complexity

ProgramTimeExtra space
Fixed / input / helper (Examples 1–3)O(n²)O(n²) for the matrix

Every cell is written once and printed once, so both fill and print are O(n²). The grid itself needs O(n²) memory.

Key Takeaways

  • Rule: fill top → right → bottom → left, then shrink $low/$high.
  • Skip corners twice: start right at $low + 1; stop left before $low.
  • printf vs PHP_EOL: cells stay on the row; echo PHP_EOL advances after each line.
  • Next series: PHP star patterns — another classic nested-loop workout.

One line: walk four edges per ring, shrink the frame, until the square is full.

Frequently Asked Questions

It fills an n×n (perfect square) grid with numbers 1..n² in a clockwise spiral path, starting at the top-left and moving inward layer by layer.
They mark the current layer's top/bottom row and left/right column. After filling four edges, increment $low and decrement $high to shrink the active rectangle.
The top row already wrote the top-right corner at ($low, $high). Starting at $low + 1 avoids writing that cell twice.
Yes. Allocate an n×n array and run (n + 1) / 2 layers. The same four edge loops work for any positive n — see Example 2.
O(n²) — every cell is assigned exactly once, so work grows with the number of cells.
Yes. Reorder the four edge fills (for example left, bottom, right, top) and adjust loop bounds so corners are not duplicated.
The innermost layer is a single cell. The last loops still work; one iteration may fill only the center (for example n=5 → center is 25).
printf('%4d', ...) stays on the same line for each cell. echo PHP_EOL ends the row after the inner print loop.
Use trim(fgets(STDIN)) and is_numeric($input), then validate (int)$input > 0.

Did you know?

Fills an n×n matrix in spiral order using $low/$high boundaries — top, right, bottom, left edges per layer. O(n²) time and space.

Next: PHP Star Patterns

Continue with another classic nested-loop pattern series.

Star patterns hub →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

12 people found this page helpful