Transforming a grid in place

Math and Geometry

Transforming a grid in place

Rotations and traversals, done with coordinate identities rather than by pushing indexes around until the tests pass.

Key idea

A rotation is two easy operations

Rotating a square grid a quarter turn clockwise, in place, looks like it needs four-way element cycling with careful bounds. There is a much easier route: transpose the grid, then reverse each row.

Transposing swaps every cell with its mirror across the main diagonal, which is one nested loop with the inner starting at the outer index so each pair is swapped once. Reversing each row is one call per row.

Neither step needs any thought about bounds, and their composition is the rotation. Deriving a hard transformation as a composition of easy ones is the technique here.

Two familiar operations compose into the rotation. Doing either in place is the part left to write.

Gotcha

The inner loop must start past the diagonal

Starting the inner loop at zero swaps every pair twice, which returns the grid to exactly where it started. The transpose appears to do nothing and the rotation comes out as a plain row reversal.

Starting at the outer index visits each unordered pair once and skips the diagonal, which needs no swapping. That single bound is the whole correctness of the step.

Tip

The other direction is the mirror

Rotating the other way is transpose then reverse the columns, or equivalently reverse the rows first and then transpose. Both compositions work and the order matters.

Rather than memorizing four variants, check one on a two-by-two grid. Ten seconds of tracing settles which composition you have, and a two-by-two is small enough to do in your head.

Key idea

Traversals with shrinking boundaries

Walking a grid in a spiral is best written with four boundaries that close in, rather than with direction vectors and turn detection. Walk the top row, then the right column, then the bottom row, then the left column, shrinking a boundary after each.

The subtlety is that after shrinking, a later pass in the same lap may have nothing left to do, so the bottom and left passes need a guard checking that the boundaries have not crossed.

Watch the four boundaries on a single row, which is the input those guards exist for.

Without that guard the single row would be walked forward and then backward, duplicating every value.

Why it works

Why only two of the four passes need a guard

The loop condition is checked before the top and right passes, so those are known to be valid. The top and right boundaries move during the lap, which is what can invalidate the bottom and left passes.

A single row and a single column are exactly the cases those guards exist for, which is why the trace above uses one. Without them, a single row is traversed forward and then backward, producing every value twice.

Key idea

Using the grid itself as storage

Some problems ask for a transformation using no extra space proportional to the grid. The move is to use part of the grid, usually the first row and column, as the marker storage.

It needs care: those cells serve two purposes at once, so whether the first row itself was affected has to be recorded separately before the markers are written, and the marked rows and columns must be applied before the first row and column themselves.

That ordering is the entire problem. Write the phases down in order before coding: record the edge cases, mark, apply to the interior, then apply to the edges.

Find the transpose bug

This is meant to reflect a square grid across its main diagonal, in place. It returns the grid completely unchanged. Click the line that is wrong.

This activity type is not wired up yet.

Rotate Image

Read the constraints first and let them tell you what complexity is expected. Derive the approach, implement it, run the tests, and submit when it passes.

Loading the workspace…

Spiral Matrix

Read the constraints first and let them tell you what complexity is expected. Derive the approach, implement it, run the tests, and submit when it passes.

Loading the workspace…

Set Matrix Zeroes

Read the constraints first and let them tell you what complexity is expected. Derive the approach, implement it, run the tests, and submit when it passes.

Loading the workspace…
← Previous