27
\$\begingroup\$

Challenge

Given a square matrix of characters (single-byte printable ASCII characters), rotate each "ring" of the matrix in opposite directions.

Let's take an example:

1 2 3 4 5
6 7 8 9 A
B C D E F
G H I J K
L M N O P

Then, the outermost ring is rotated clockwise 90 degrees, like so:

1 2 3 4 5    L G B 6 1
6       A    M       2
B       F => N       3
G       K    O       4
L M N O P    P K F A 5

The second ring is rotated counterclockwise 90 degrees:

7 8 9    9 E J
C   E => 8   I
H I J    7 C H

The final ring is rotated clockwise 90 degrees, but since it is a single number (letter in our example), then it is not really affected.

The final result is:

L G B 6 1
M 9 E J 2
N 8 D I 3
O 7 C H 4
P K F A 5

If the matrix has an even side length, the innermost ring will be a 2x2 square and should still be rotated.

Input

A list of lists in any reasonable standard format. For example, a newline-delimited space-delimited string or a list of space-delimited strings is acceptable, but a list of the values as rings around the matrix is not acceptable. The characters are not necessarily unique.

Output

A list of lists in any reasonable standard format. Same rules as the input.

Test Cases

1 2 3    7 4 1
4 5 6 => 8 5 2
7 8 9    9 6 3

1 2 3 4 5 6    Y S M G A 1
A B C D E F    Z E K Q W 2
G H I J K L => ! D O I V 3
M N O P Q R    @ C P J U 4
S T U V W X    # B H N T 5
Y Z ! @ # $    $ X R L F 6

Credits

Heavily inspired by a related challenge that rotates each element counterclockwise one position (not by 90 degrees).

\$\endgroup\$
8
  • \$\begingroup\$ Related \$\endgroup\$ – rahnema1 Jun 21 '17 at 18:20
  • \$\begingroup\$ @rahnema1 Right, I remember that post. This post is mostly inspired by that one; I will credit. Thanks! \$\endgroup\$ – hyper-neutrino Jun 21 '17 at 18:21
  • \$\begingroup\$ @Mr.Xcoder Whoops. You are right, thanks. \$\endgroup\$ – hyper-neutrino Jun 21 '17 at 18:21
  • \$\begingroup\$ @HyperNeutrino can we take the dimension of the matrix as a part of input? \$\endgroup\$ – Uriel Jun 21 '17 at 19:20
  • \$\begingroup\$ All characters in your examples are unique. Will this always be the case? \$\endgroup\$ – Dennis Jun 21 '17 at 19:27
10
\$\begingroup\$

Haskell, 94 bytes

An anonymous function taking and returning a list of Strings.

Use as (cycle[t.r,r.t,r.t,r.t]?)["123", "456", "789"].

(cycle[t.r,r.t,r.t,r.t]?)
(g:h)?(a:b)=g$a:h?t(r b)
_?a=a
r=reverse;t=zipWith(:)`foldr`repeat[]

Try it online!

How it works

  • r is reverse. t is one byte shorter than importing Data.List.transpose. t.r rotates a list of lists 90 degrees clockwise, and r.t rotates it counterclockwise.
  • The operator ? takes two arguments, a list of functions and a matrix as a list of strings.
    • An empty matrix is just returned.
    • Otherwise, ? strips the first function f off the list of functions, and the first line a off the matrix.
    • Then it rotates the remainder b of the matrix clockwise, and recurses with that and the remaining functions. This gradually strips the matrix from the outside in, one ring each four steps.
    • Then it prepends the original line a to the result, and applies the function f to it to adjust the orientation of the matrix.
  • The anonymous function calls ? with the input matrix as a list of strings, and an infinite list of functions, which repeats cyclically every four steps.
    • For most of the steps the function is counterclockwise rotation, which undoes the implicit clockwise rotation done by ? when recursing.
    • However, the first step and every fourth step afterwards is instead clockwise rotation.
      • This function is applied when a ring of the matrix is complete, causing each ring to be 180 degrees rotated with respect to the next one.
      • By luck, this is also the correct transformation to apply to the final, completed matrix to get the final result.
\$\endgroup\$
7
\$\begingroup\$

Python 2, 104 bytes

def f(x):l=len(x)-1;r=range(l+1);return[[[x[l-i][j],x[i][l-j]][min(i,j,l-i,l-j)%2]for i in r]for j in r]

Try it online!

x[l-i][j] are the coordenates of a clockwise turn, x[i][l-j] for a counterclowise turn. min(i,j,l-i,l-j)%2 is used to pick the right direction

\$\endgroup\$
3
  • \$\begingroup\$ returning rotations recursively. \$\endgroup\$ – tuskiomi Jun 21 '17 at 20:10
  • \$\begingroup\$ @tuskiomi hmm?? \$\endgroup\$ – Rod Jun 21 '17 at 21:35
  • \$\begingroup\$ @tuskiomi I tried a recursive approach in ES6. It was about twice as long as a simple port of this answer... \$\endgroup\$ – Neil Jun 22 '17 at 12:28
4
\$\begingroup\$

Mathematica, 113 bytes

r=Reverse;(l=Length[s=#];Table[s[[i+1;;l-i,i+1;;l-i]]=r/@r@s[[i+1;;l-i,i+1;;l-i]],{i,⌊l/2⌋}];r/@Transpose@s)&


it is better to input as char string like "E" for special letters like E,I...

input

[{{1, 2, 3, 4, 5, 6}, {A, B, C, D, "E", F}, {G, H, "I", J, K, L}, {M, N, O, P, Q, R}, {S, T, U, V, W, X}, {Y, Z, "!", "@", "#", "&"}}]

output

{{Y, S, M, G, A, 1}, {Z, "E", K, Q, W, 2}, {"!", D, O, "I", V, 3}, {"@", C, P, J, U, 4}, {"#", B, H, N, T, 5}, {"&", X, R, L, F, 6}}

\$\endgroup\$
3
\$\begingroup\$

Octave, 86 bytes

@(a){k=a;k(x=2:end-1,x)=0;a=rot90(a);a(m)=rot90(a,-2)(m=~mod(bwdist(+k,'ch'),2));a}{5}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Unicode), 35 bytes (SBCS)

Full program. Prompts for APL matrix expression. Requires 0-based indexing.

⍉⌽m⊣{(b↓e↓m)←⌽⊖b↓m↓⍨e←-b←2⍴⍵}¨⍳≢m←⎕

Try it online!

m←⎕ prompt for matrix and assign to m

 tally the number of rows in it

ɩndices zero through one less than that

{ apply the following lambda to each element (denoted in the code) of that:

2⍴⍵reshape the index to a two-element list

b← assign to b (for beginning)

- negate that

e← assign to e (for end)

m↓⍨ drop that many (negative, so trailing) rows and columns from m

b↓ drop that many leading rows and columns from that

 flip upside down

 mirror

(m)← assign to the following sub-array of m:

  e↓ drop the appropriate number of rows and columns from the end (bottom right)

  b↓ drop the appropriate number of rows and columns from the beginning (top left)

m⊣ ignore the pass-through values of all the assignments, in favour of the updated value of m

 mirror

 transpose

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Unicode), 81 bytes

{u⊃+/{⌽[1+2|⍵]∘⍉w×1@(y/⍨∨/¨(⍵,x)∘∊¨y←,∘.,⍨(⍵-1)↓⍳x←1+|⍵-≢w)⊢0×w}¨⍳⌈.5×≢w←⍵}u←⎕UCS

Try it online!

A 2-train which takes the matrix as its right argument.

The idea behind this is to peel the matrix into its rings, like so:

┌──────┬──────┬──────┬──────┐
│123456│123456│      │      │
│ABCDEF│A    F│ BCDE │      │
│GHIJKL│G    L│ H  K │  IJ  │
│MNOPQR│M    R│ N  Q │  OP  │
│STUVWX│S    X│ TUVW │      │
│YZ!@#$│YZ!@#$│      │      │
└──────┴──────┴──────┴──────┘

Then each of these rings are rotated left/right based on their index.

My algorithm for getting the rings has a lot of room for improvement (Porting the python solution may be shorter).

Explanation

⎕UCS convert the matrix to its unicode values

u←⎕UCS store conversion function as u

{...} apply the following function on the matrix:

w←⍵ store argument as w

⍳⌈.5×≢ range 1..ceil(length(w)/2)


Getting the rings

{...}¨ for each value i in the range:

0×w to the input, converted to zeroes,

1@(...) replace the following coordinates with 1s:

1+|⍵-≢⍵ upper limit: length(w) - i

(⍵-1)↓⍳ create range from i to that

,∘.,⍨ get all points in that range

y← store in y

∨/¨(⍵,x)∘∊¨ check which ones are part of the ring, and get a list of booleans

y/⍨ filter y using the boolean array

multiply w with that (vectorizes)

⌽[1+2|⍵]∘⍉ Rotate right if i is odd, otherwise left


Finally,

+/ sum all the matrices (vectorizes)

unwrap

u convert back to character matrix.

\$\endgroup\$
2
\$\begingroup\$

R, 98 bytes

f=function(m,r=T,d=length(m)^.5){n=t(m)[d:1,]
if(r)n[]=rev(n)
if(d>2)n[e,e]=f(m[e<-3:d-1,e],!r)
n}

Try it online!

How?
At each recursive step, rotate the matrix clockwise by transposing it and reversing the rows. Then, if it should be an anticlockwise rotation, reverse all the elements. Finally, replace the 'internal matrix' with the results of a recursive call, with the rotation set to the opposite direction.

interlaced_rotate=
f=function(m,r=T,       # recursive function: 
                        # m=matrix
                        # r=direction of rotation (TRUE=clockwise, FALSE=anticlockwise)
d=length(m)^.5){        # d=length of matrix side
  n=t(m)[d:1,]          # n=m rotated clockwise by transposing & reversing rows
  if(r)n[]=rev(n)       # if it's an anticlockwise rotation, reverse the elements
  if(d>2)               # if the 'internal matrix' has a side-length of >1:
    n[e,e]=             # replace it with
    f(m[e<-3:d-1,e],!r) # a recursive call, reversing the direction
n}                      # finally, return n
\$\endgroup\$
2
\$\begingroup\$

Jelly, 19 18 bytes

ŒJUC;L‘_ɗ@ṂḂʋ¦€œịṁ

Try it online!

Explanation

ŒJUC;L‘_ɗ@ṂḂʋ¦€œịṁ   Main monadic link
ŒJ                   Multidimensional indices
  U                  Reverse each
              €      For each
            ʋ          (
    ;                    Join with
        ɗ                (
     L   @                 Length of the input
      ‘                    Increment
       _                   Subtract the argument
                         )
          Ṃ              Minimum
           Ḃ             Parity
            ʋ          )
             ¦         At the obtained index
   C                   subtract it from 1
               œị    Index into the input
                 ṁ   Reshape to be the same as the input
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.