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 indexk
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.