Clockwise matrix rotation

18

The title pretty much describes it all. Given as input a \$n \times m\$ matrix and an integer \$i\$ create a complete function/program that returns the matrix \$i\$ times clockwise rotated by \$90^\circ\$.

Rules:

  • as matrix you can use any convenient representation you like e.g. a list of lists etc...
  • matrix values can be positive and/or negative integer numbers
  • \$n\$ and \$m\$ are of course always positive integers between 1 and 10
  • \$i\$ can be any valid integer which belongs in the following range: \${0...10^5}\$
  • Standard rules & winning criteria apply but no "winning" answer will be chosen.

EDIT: I had to edit the initial question because for some programming languages it takes too long to compute the result for \$i\in\{0...10^7\}\$. There is a workaround to it but since it's a code-golf just make sure that it simply runs successfully for at least \$i\in\{0...10^5\}\$.

Some test cases:

==== example 1 ====
Input:
5
[[1, 3, 2, 30,],
 [4, 9, 7, 10,],
 [6, 8, 5, 25 ]]

Expected Output:
[[ 6  4  1],
 [ 8  9  3],
 [ 5  7  2],
 [25 10 30]]

==== example 2 ====
Input:
100
[[1]]

Expected Output:
[[1]]

==== example 3 ====
Input:
15
[[150,    3,  2],
 [  4, -940,  7],
 [  6, 8000,  5]]

Expected Output:
[[   2    7    5],
 [   3 -940 8000],
 [ 150    4    6]]

==== example 4 ====
Input:
40001
[[1, 3, 9]]

Expected Output:
[[1],
 [3],
 [9]]
```

game0ver

Posted 2019-11-27T22:54:05.983

Reputation: 621

Answers

7

APL (Dyalog Unicode), 7 bytes

⌽∘⍉⍣⎕⊢⎕

Try it online!

 prompt for matrix expression from stdin

 yield that

 prompt for \$i\$ expression from stdin

 do the following that many times

 transpose

 and then

 mirror

Adám

Posted 2019-11-27T22:54:05.983

Reputation: 37 779

2

Nice, I really liked that it even works for $i$ of $10^7$. I had to lower that in the requirements because for some languages tio.run wouldn't terminate...

– game0ver – 2019-11-27T23:24:58.313

1@game0ver Yeah, APL is generally quite fast when it comes to munging arrays. Even $10^8$ only takes about 20 seconds on TIO. – Adám – 2019-11-27T23:35:02.083

2Wow, the character for transpose and mirror looks suitable – justhalf – 2019-11-29T05:35:16.947

@justhalf Yes, APL is like that. Can you guess what flip-upside-down looks like? – Adám – 2019-11-29T08:32:04.263

Something like this ⦵? – justhalf – 2019-11-29T09:03:06.053

1

@justhalf Basically. Unicode has many homoglyphs. APL prefers the Unicode APL range, so this is

– Adám – 2019-11-29T11:50:12.643

5

Pyth, 7 6 bytes

uC_GQE

Try it online!

-1 Thanks to @FryAmTheEggman

Rotates the matrix by reversing the order of rows and taking the transpose. Takes and returns lists of lists.

How it works

uC_GQE
u    E - Reduce the second input
  _G   - By reversing the order of rows
 C     - And transposing
    Q  - An amount of times equal to the first input  

frank

Posted 2019-11-27T22:54:05.983

Reputation: 941

5

J, 7 bytes

|:@|.^:

Try it online!

An adverb train. Right argument is the matrix, left argument is the repetition count.

How it works

|:@|.^:
     ^:  Repeat the function:
   |.      Reverse vertically
  @        and then
|:         Transpose
         Absent right argument to `^:`:
           bind to the left argument (repeat count)

Bubbler

Posted 2019-11-27T22:54:05.983

Reputation: 16 616

5

Ruby, 39 bytes

->m,n{n.times{m=m.reverse.transpose};m}

Try it online!

G B

Posted 2019-11-27T22:54:05.983

Reputation: 11 099

5

K (oK), 6 bytes

(+|:)/

Try it online!

Galen Ivanov

Posted 2019-11-27T22:54:05.983

Reputation: 13 815

4

Japt -R, 2 bytes

zV

Try it

Rotate matrix by 90 degrees 2nd input times

AZTECCO

Posted 2019-11-27T22:54:05.983

Reputation: 2 441

1OK, this one might be hard to beat. – Adám – 2019-11-27T23:43:14.617

@Adám agreed, Japt fits this challenge very well :p – AZTECCO – 2019-11-27T23:53:50.480

1@AZTECCO really impressive!!! – game0ver – 2019-11-27T23:54:44.880

I knew this would be the solution just from the challenge title! I also knew someone would have beaten me to it! – Shaggy – 2019-11-28T14:20:45.860

1I was there at the right time @Shaggy , couldn't miss it! – AZTECCO – 2019-11-28T15:33:09.257

4

Jelly, 4 bytes

Naive implementation. There might be a shorter way I'm not aware of.

ṚZ$¡

Try it online!

Arnauld

Posted 2019-11-27T22:54:05.983

Reputation: 111 334

Nice, but the last test case fails since for both $i=40001$ and $i=40000$ it gives the same result. – game0ver – 2019-11-27T23:51:30.207

1@game0ver The output is actually different, but displayed the same way. I've added some code in the footer to format it. – Arnauld – 2019-11-28T00:00:13.090

yep you are correct! Thanks for editing :) – game0ver – 2019-11-28T00:08:13.083

2I think this is as short as you can get at present. Matrix rotation is already on my wish list of possible new Jelly links that I may get round to suggesting at some point – Nick Kennedy – 2019-11-29T10:08:26.463

4

Python 2, 44 bytes

f=lambda A,i:i%4and f(zip(*A[::-1]),i-1)or A

Try it online!

Input/output is a list of tuples. (The %4 is a workaround for Python's recursion limit; could save a byte otherwise).

Chas Brown

Posted 2019-11-27T22:54:05.983

Reputation: 8 959

Nice! Yep that's the workaround (%4) I'm talking about in the description. A way to skip that would be using numpy but I really like the naive implementation. Also you could save 2 bytes by placing f= into Header in TIO! – game0ver – 2019-11-28T10:43:07.070

1@game0ver They can't actually do that to save bytes since this is a recursive function - it needs to be named so they can call it. – FryAmTheEggman – 2019-11-28T16:31:48.407

@FryAmTheEggman good catch! You are right! – game0ver – 2019-11-28T17:04:39.750

3

Haskell, 50 bytes

(!!).iterate(foldr(zipWith$flip(++).pure)e)
e=[]:e

Try it online!

totallyhuman

Posted 2019-11-27T22:54:05.983

Reputation: 15 378

3

05AB1E (legacy), 3 bytes

Føí

Takes \$i\$ as first input; matrix the second.

Try it online or verify all test cases.

Explanation:

F    # Loop the (implicit) input-integer amount of times:
 ø   #  Zip/transpose the matrix; swapping rows/columns
     #  (this will take the (implicit) input in the first iteration)
  í  #  Reverse each row
     # (after the loop, the resulting matrix is output implicitly)

NOTE: Uses the legacy version only because of performance. The last test case times out in the rewrite version. Both the legacy and rewrite versions would be the same, though.

Kevin Cruijssen

Posted 2019-11-27T22:54:05.983

Reputation: 67 575

2

JavaScript (ES6), 58 bytes

Takes input as (i)(matrix).

i=>g=m=>i--?g(m[0].map((_,x)=>m.map(r=>r[x]).reverse())):m

Try it online!

Note: The last test case was edited to prevent a recursion error. We can obviously use i--&3 (60 bytes) to support much larger values.

Arnauld

Posted 2019-11-27T22:54:05.983

Reputation: 111 334

2

Octave, 17 bytes

Unfortunately rot90 rotates the input counterclockwise.

@(x,i)rot90(x,-i)

Try it online!

flawr

Posted 2019-11-27T22:54:05.983

Reputation: 40 560

2

MATL, 5 3 bytes

-2 bytes thanks to @LuisMendo!

_X!

Try it online!

flawr

Posted 2019-11-27T22:54:05.983

Reputation: 40 560

2

Java 8, 141 138 131 130 bytes

(m,i)->{for(int t[][],a,b,j;i-->0;m=t)for(t=new int[b=m[0].length][a=m.length],j=a*b;j-->0;)t[j%b][j/b]=m[a-j/b-1][j%b];return m;}

-7 bytes thanks to @OlivierGrégoire.

Try it online.

Code explanation:

(m,i)->{                 // Method with int-matrix and int parameters and int-matrix return
  for(int t[][],         //  Temp int-matrix as replacement
          a,b,           //  Temp integers used for the dimensions
          j;             //  Temp integer for the inner loop
      i-->0;             //  Loop the input `i` amount of times:
      m=t)               //    After every iteration: replace the input-matrix `m` with `t`
    for(t=new int[b=m[0].length][a=m.length],
                         //   Create a new temp-matrix `t` with dimensions `b` by `a`,
                         //   where `b` & `a` are the amount of columns & rows of matrix `m`
        j=a*b;           //   Set `j` to the product of these dimensions
        j-->0;)          //   And inner loop in the range [`j`, 0):
      t                  //  Replace the value in `t` at position:
       [j%b]             //   `j%b` (let's call this row A),
            [j/b]        //   `j/b` (let's call this column B)
        =m               //  And replace it with the value in `m` at position:
          [a-j/b-1]      //   `a-j/b-1` (which is the reversed column B as row,
                         //     so it both transposes and reverses at the same time),
                   [j%b];//   `j%b` (which is row A as column)
  return m;}             //  And finally return the new int-matrix

To save bytes, the inner loop is a single loop and uses j/a and j%a as cell positions. So a loop like this:

for(r=a;r-->0;)for(c=b;c-->0;)t[c][r]=m[b-r-1][c];

Has been golfed to this:

for(j=a*b;j-->0;)t[j%b][j/b]=m[a-j/b-1][j%b];

to save 5 bytes.

Kevin Cruijssen

Posted 2019-11-27T22:54:05.983

Reputation: 67 575

1131 bytes – Olivier Grégoire – 2019-11-29T09:12:56.547

Explanation of the above: I restarted it from scratch trying to use simply new int[m[0].length][m.length]. It seemed to have worked. The rest is basically your code. So in the end the golf came from moving the variable allocation where needed most. – Olivier Grégoire – 2019-11-29T09:17:02.450

1@OlivierGrégoire I was quite proud of this one, but had the feeling it could still be golfed. ;) Btw, 1 more byte can be saved by removing that temp variable s and use a-j/b-1 instead of a+~s again. – Kevin Cruijssen – 2019-11-29T09:22:09.273

1Indeed, that's a one more saved byte. I hadn't passed the code again under full review ;) But to be honest, you did the bigger job with your first answer. – Olivier Grégoire – 2019-11-29T09:28:58.580

I've removed that general explanation, since it's now the same as the code, haha. ;) – Kevin Cruijssen – 2019-11-29T09:35:24.267

2

R, 64 bytes

r=function(x,i){o=x;n=0;while(n<i){o=t(apply(o,2,rev));n=n+1};o}

Try it online!

Not really efficient...

Uses rotation approach proposed by Matthew Lundberg

John

Posted 2019-11-27T22:54:05.983

Reputation: 171

Hi there, and welcome to R golfing! I like this approach. There are still a bunch of golfs available, e.g., this for 48 bytes. Feel free to join the R golf chatroom to ask any golfing questions you might have, and read these tips. Happy golfing!

– Giuseppe – 2019-12-02T21:12:41.973

To speed it up, you can do something like i%%4 in the stop condition. – Giuseppe – 2019-12-02T21:13:47.923

1

Pari/GP, 37 bytes

f(m,n)=for(i=1,n,m=Mat(Vecrev(m~)));m

Try it online!

alephalpha

Posted 2019-11-27T22:54:05.983

Reputation: 23 988

1

Julia 1.0, 6 bytes

Kind of cheating, but Julia has a built in rotl90 function, that does exactly that.

rotl90

Try it online!

user3263164

Posted 2019-11-27T22:54:05.983

Reputation: 381

1No, no cheat at all! It's also pretty fast with very large values of $i$ e.g. $i^{11}$ etc... – game0ver – 2019-11-29T11:31:11.547

-1

Mathematica, 32 bytes

a = {{3, 4, 5}, {5, 6, 7}, {8, 9, 10}, {11, 12, 13}};

Nest[Reverse /@ Transpose[#] &, a, i] 

David G. Stork

Posted 2019-11-27T22:54:05.983

Reputation: 213