Rotate every 2x2 block in a matrix

CJam (42 40 bytes)

{(\@2$,(/.{@a@a+z(\@.{4,={+2/zW%~}*}z~}}

Online demo

Basically this applies the same technique twice in order to fold the block

{4,={+2/zW%~}*}

which operates on a 2x2 matrix and a number of times to rotate.

[first row] [[second row] [third row] ... [last row]] [value_0 value_1 ... value_n]

can be processed with

.{block}

and has the effect of

[first row]
[second row] value_0 {block}~
[third row] value_1 {block}~
...

because . (like % in CJam) doesn't gather the results into an array until it's finished.


APL (Dyalog Unicode), 37 35 bytes

{⌽∘⍉@⍺⊢⍵}/⌽(⊂,{(4|⎕)/,⊢∘⊂⌺2 2⍳⍴⍵})⎕

Try it online!

Switched to a more straightforward method after I realized @ also accepts a matrix of coordinates. Then we don't need to fiddle with the coordinate order; we extract the submatrix coordinates with ⊢∘⊂⌺2 2, and just rotate them directly using ⌽∘⍉.


APL (Dyalog Unicode), 37 bytes

{1⌽@⍺⊢⍵}/⌽(⊂,{(4|⎕)/,2,∘⌽/2,⌿⊂¨⍳⍴⍵})⎕

Try it online!

A full program that takes the matrix, then the vector of rotation amounts. Prints the resulting matrix with a leading space.

@ can extract the elements at certain positions, manipulate them, and place them back into the original matrix, which is great for 2×2 rotation. In particular, 1⌽@(1 1)(2 1)(2 2)(1 2) extracts the top left submatrix [a b][c d] into a vector a c d b, rotates once to the left (1⌽) into c d b a, then puts the values back so that the submatrix becomes [c a][d b]. This achieves rotating the submatrix exactly once.

{1⌽@⍺⊢⍵}/⌽(⊂,{(4|⎕)/,2,∘⌽/2,⌿⊂¨⍳⍴⍵})⎕

⍝ Read from right:
     ⎕  ⍝ Take the matrix from stdin
{...}   ⍝ Pass to the dfn as ⍵
          ⍳⍴⍵  ⍝ Matrix of 2D coordinates of ⍵
     2,⌿⊂¨     ⍝ Pair vertically adjacent coordinates
2,∘⌽/          ⍝ Catenate horizontally adjacent coordinate pairs,
               ⍝ flipping the right one so that it looks like (1 1)(2 1)(2 2)(1 2)
      ,  ⍝ Flatten the matrix of lists of coordinates
(4|⎕)/   ⍝ Copy each (Rotations modulo 4) times
⌽(⊂,...)  ⍝ Prepend the original matrix enclosed and reverse the entire array,
          ⍝ so that it is suitable for RTL reduce
{      }/  ⍝ RTL reduce by...
 1⌽@⍺⊢⍵    ⍝ Take the matrix ⍵ and rotate once at coordinates ⍺

CJam, 65 63 60 55 bytes

There must be a better way to do this...

{_e_\z,:N(@/Ta*ee{~4,=,f{;1$,,\[XTN_)]f+_(+er\f=}~}/N/}

This is an unnamed function that expects the instructions and the matrix (in that order) on the stack and leaves the resulting matrix in their place.

Test it here.

Explanation

I don't feel like writing the full breakdown for the code right now, so here is a rough overview:

  • 2D array manipulation is a pain in CJam, so I'm instead unrolling the matrix, compute each rotation as a permutation of the elements at specific positions and then split the array into rows again at the end. The width of the matrix is stored in N.
  • A rotation at position k in the unrolled array changes four indices: k <- k+1, k+1 <- k+1+N, k+N <- k, k+1+N <- k+1. For each index k along the instruction list, I compute a permutation corresponding to this, and apply it to the unrolled input array.
  • This leaves the problem, that in the linear array some rotations will be positioned with its top left corner in the last column of the input. To skip these, I riffle zeroes into the instruction list, such that these invalid 2x2 sub-blocks are technically processed, but with a no-op.