TransWikia.com

Rotate every 2x2 block in a matrix

Code Golf Asked on November 21, 2021

The Challenge

Given a n x m matrix with n > 1 and m > 1 filled with integers

1 2 3
4 5 6

and a list of integers with exactly as many values as 2x2 blocks in the matrix ((n-1)*(m-1) if you need the exact number)

[1, 2]

Output the matrix with every 2x2 block rotated by the current value in the list in the given order. The example above would yield

4 6 2
5 3 1

The first block gets rotated one time to the right and the second block gets rotated two to the right.

Notes

  • A positive integer means you rotate right by that many steps.
  • A negative integer means you rotate left by that many steps.
  • A zero means that you don’t rotate.
  • You rotate the blocks row-wise. That means that you start in the first row and go to the right. Once you rotated every block in that row you go to the next one. At the end every block was rotated exactly once.
  • Keep in mind that the blocks overlap each other. The first matrix above has the blocks [[1,2],[4,5]] and [[2,3],[5,6]] for example.
  • Each rotation of a block affects the rotation on the adjacent blocks. This is why you have to do the rotations in the pattern described above.

Rules

  • You may take the input in the most convenient format. Please specify in your answer which one you use. This does not allow you to read the matrix block-wise though.
  • Function or full program allowed.
  • Default rules for input/output.
  • Standard loopholes apply.
  • This is , so lowest byte-count wins. Tiebreaker is earlier submission.

Test cases

Input format here is a list of lists for the matrix and a normal list for the values.

[[1,2],[3,4]], [-3] -> [[4,1],[3,2]]
[[1,1,1],[1,1,1]], [-333, 666] -> [[1,1,1],[1,1,1]]
[[1,2,3],[4,5,6]], [1,2] -> [[4,6,2],[5,3,1]]
[[1,2,3],[4,5,6],[7,8,9]], [4,0,12,-20] -> [[1,2,3],[4,5,6],[7,8,9]]
[[1,2,3,4,5],[5,4,3,2,1],[1,2,3,4,5]], [2,-3,4,1,6,24,21,-5] -> [[4,1,5,2,4],[2,1,3,5,5],[3,2,4,3,1]]

Happy Coding!

4 Answers

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 ⍺

Answered by Bubbler on November 21, 2021

Python 2, 166 159 bytes

A,R=input();m=~-len(A[0])
for j,r in enumerate(R):exec r%4*"a,b,c,d=A[j/m][j%m:][:2]+A[j/m+1][j%m:][:2];A[j/m][j%m:j%m+2]=c,a;A[j/m+1][j%m:j%m+2]=b,d;"
print A

Try it online!

Answered by Jonathan Frech on November 21, 2021

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.

Answered by Peter Taylor on November 21, 2021

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+_(+erf=}~}/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.

Answered by Martin Ender on November 21, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP