26
\$\begingroup\$

Take a square matrix containing positive integers as input, and calculate the "rotated sum" of the matrix.

Rotated sum:

Take the sum of the original matrix and the same matrix rotated 90, 180 and 270 degrees.

Suppose the matrix is:

 2    5    8
 3   12    8
 6    6   10

then the rotated sum will be:

2    5    8     8    8   10    10    6    6     6    3    2
3   12    8  +  5   12    6  +  8   12    3  +  6   12    5  = 
6    6   10     2    3    6     8    5    2    10    8    8   

26   22   26
22   48   22
26   22   26

Test cases:

Input and output separated by dashes, different test cases separated by a newline. Test cases in more convenient formats can be found here.

1
-------------
4

1 3
2 4
-------------
10   10 
10   10    

14    6    7   14
 6   12   13   13
 6    2    3   10
 5    1   12   12
-------------
45   37   24   45
24   30   30   37
37   30   30   24
45   24   37   45    

14    2    5   10    2
18    9   12    1    9
 3    1    5   11   14
13   20    7   19   12
 2    1    9    5    6
-------------
24   29   31   41   24
41   49   31   49   29
31   31   20   31   31
29   49   31   49   41
24   41   31   29   24

Shortest code in bytes in each language wins. Explanations are highly encouraged!

\$\endgroup\$

29 Answers 29

9
\$\begingroup\$

Python 2, 78 bytes

Thanks to Dennis for golfing two bytes off my previous recursive approach.

f=lambda*l:l[3:]and[map(sum,zip(*d))for d in zip(*l)]or f(zip(*l[0][::-1]),*l)

Try it online! or See a test suite.


Python 2, 80 81 83 85 bytes (non-recursive)

Takes input as a singleton list.

l=input()
exec"l+=zip(*l[-1][::-1]),;"*3
print[map(sum,zip(*d))for d in zip(*l)]

Try it online!

Code functionality

Since this is quite length-ish to analyse it as a whole, let's check it out piece-by-piece:

f = lambda *l:                # This defines a lambda-function that can accept any number
                              # of arguments (the matrix) using starred expressions.
l[3:] and ...X... or ...Y...  # If l[3:] is truthy (that is, the length of the list is
                              # higher than 3), return X, otherwise Y.

[map(sum,zip(*d))for d in zip(*l)]     # The first expression, X.
[                                ]     # Start a list comprehension, that:
                 for d in              # ... Iterates using a variable d on:
                          zip(*l)      # ... The "input", l, transposed.
         zip(*d)                       # ... And for each d, transpose it...
 map(sum,       )                      # ... And compute the sum of its rows.
                                       # The last two steps sum the columns of d.

f(zip(*l[0][::-1]),*l)     # The second expression, Y. This is where the magic happens.
f(                   )     # Call the function, f with the following arguments:
  zip(*          )         # ... The transpose of:
       l[0][::-1]          # ...... The first element of l (the first arg.), reversed.
                  ,        # And:
                   *l      # ... l splatted. Basically turns each element of l
                           # into a separate argument to the function.

And for the second program:

l=input()                                # Take input and assign it to a variable l.
                                         # Note that input is taken as a singleton list.

exec"l+=zip(*l[-1][::-1]),;"*3           # Part 1. Create the list of rotations.
exec"                     ;"*3           # Execute (Do) the following 3 times:
     l+=                 ,               # ... Append to l the singleton tuple:
        zip(*           )                # ...... The transpose of:
             l[-1][::-1]                 # ......... The last element of l, reversed.

print[map(sum,zip(*d))for d in zip(*l)]  # Part 2. Generate the matrix of sums.
print                                    # Output the result of this expression:
     [                for d in        ]  # Create a list comprehension, that iterates
                                         # with a variable called "d" over:
                               zip(*l)   # ... The transpose of l.
      map(sum,       )                   # ... And computes the sum:
              zip(*d)                    # ... Of each row in d's transpose.
                                         # The last 2 steps generate the column sums.

TL;DR: Generate the list of matrices needed by rotating the input 3 times by 90-degrees and collecting the results. Then, get the sums of the columns of each matrix in the result's transpose.

\$\endgroup\$
  • \$\begingroup\$ f=lambda*l:l[3:]and[map(sum,zip(*d))for d in zip(*l)]or f(zip(*l[0][::-1]),*l) saves two bytes with "normal" input. Try it online! \$\endgroup\$ – Dennis Jan 20 '18 at 13:21
  • \$\begingroup\$ @Dennis Thank you! I thought lambda*l wasn't possible in Python 2 for some reason. \$\endgroup\$ – Mr. Xcoder Jan 20 '18 at 13:25
  • \$\begingroup\$ You can't do x,*y=1,2,3 in Python 2.7 or [*x] in Python 3.4, but starred expressions can be used for function arguments even in Python 1.6. Try it online! \$\endgroup\$ – Dennis Jan 20 '18 at 13:31
8
\$\begingroup\$

Octave, 29 bytes

@(x)(y=x+rot90(x))+rot90(y,2)

Try it online!

Explanation

This adds the input matrix with a 90-degree rotated version of itself. The result is then added with a 180-degree rotated version of itself.

\$\endgroup\$
5
\$\begingroup\$

Clean, 110 bytes

import StdEnv,StdLib
r=reverse
t=transpose
z=zipWith(+)
$m=[z(z(r b)a)(z(r c)d)\\a<-m&b<-r m&c<-t m&d<-r(t m)]

Try it online!

From the matricies:

  • X = transpose(reverse M): 90-degree rotation
  • Y = reverse(map reverse M): 180-degree rotation
  • Z = reverse(transpose M): 270-degree rotation

This zips the addition operator over M and X, as well as Y and Z, and then over the results.

\$\endgroup\$
5
\$\begingroup\$

Wolfram Language (Mathematica), 28 bytes

Sum[a=Reverse@a,{a=#;4}]&

is \[Transpose].

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Nice solution. I tried ReplacePart[#,{a_,b_}:>Tr@Extract[#,{{a,b},{b,-a},{-a,-b},{-b,a}}]]& and also Plus@@NestList[Reverse@#&,#,3]& \$\endgroup\$ – Kelly Lowder Jan 21 '18 at 3:16
5
\$\begingroup\$

Julia 0.6, 29 bytes

x*y=rotr90(y,x)
!x=x+1x+2x+3x

Try it online!

I couldn't get below LukeS's solution

But in trying I did come up with this, which I think is kinda cute.

First we redefine multiplication to be the rotate operation, where there first time is the number of times to rotate. So since julia multipes by juxtaposition then: 1x becomes rotr90(x,1) and 3x becomes rotr90(x,3) etc.

Then we write out the sum.

\$\endgroup\$
5
\$\begingroup\$

Julia 0.6, 28 24 bytes

~A=sum(rotr90.([A],0:3))

Try it online!

~A=sum(rotr90.([A],0:3)) #
~                        # redefine unary operator ~
 A                       # function argument
               [A]       # put input matrix A into a list with one element
                   0:3   # integer range from 0 to 3
       rotr90.(   ,   )  # apply function rotr90 elementwise, expand singleton dimensions
       rotr90.([A],0:3)  # yields list of rotated matrices:
                         # [rotr90(A,0), rotr90(A,1), rotr90(A,2), rotr90(A,3)]
  sum(                )  # sum
\$\endgroup\$
  • 1
    \$\begingroup\$ It is worth perhaps noting that to do the [1] example on should do ~reshape([1], (1,1)) because that is how a 1x1 matrix is declared in julia 0.6. \$\endgroup\$ – Lyndon White Jan 21 '18 at 13:09
4
\$\begingroup\$

MATL, 9 bytes

i3:"G@X!+

Try it at MATL Online

Explanation

i       # Explicitly grab the input matrix
3:"     # Loop through the values [1, 2, 3], and for each value, N:
  G     # Grab the input again
  @X!   # Rotate the value by 90 degrees N times
  +     # Add it to the previous value on the stack
        # Implicitly end the for loop and display the resulting matrix
\$\endgroup\$
4
\$\begingroup\$

Octave, 33 bytes

@(a)a+(r=@rot90)(a)+r(a,2)+r(a,3)

Try it online!

Explanation:

(r=@rot90) in an inline way of creating a function handle r used to rotate the matrix 90 degrees. If a second argument, k is given to r then it will rotate the matrix k*90 degrees. So this is equivalent to the pseudo code:

a + rot90(a) + rot180(a) + rot270(a)
\$\endgroup\$
3
\$\begingroup\$

Jelly, 7 bytes

ZU+µUṚ+

Try it online!

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

Pyth, 13 bytes

m+MCdC.u_CN3Q

Try it online!

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

J, 16 15 bytes

[:+/|.@|:^:(<4)

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ This is a perfect challenge for ^:. Clever solution! \$\endgroup\$ – cole Jan 20 '18 at 18:15
  • \$\begingroup\$ That's an elegant solution! \$\endgroup\$ – Galen Ivanov Jan 20 '18 at 18:24
3
\$\begingroup\$

MATL, 7 bytes

,t@QX!+

Try it at MATL Online!

Explanation

Port of my Octave answer.

,        % Do twice
  t      %   Duplicate. Takes input (implicit) the first time
  @Q     %   Push 1 in the first iteration, and 2 in the second
  X!     %   Rotate by that many 90-degree steps
  +      %   Add
         % End (implicit). Display (implicit)
\$\endgroup\$
3
\$\begingroup\$

R, 69 64 bytes

function(x,a=function(y)apply(y,1,rev))x+a(x)+a(a(x))+a(a(a(x)))

Try it online!


Attempt number three at codegolf. From 69 to 64 bytes thanks to Giuseppe!

\$\endgroup\$
  • \$\begingroup\$ Moving a to a function argument will save bytes by allowing you to get rid of the {} around the function body. Also, porting Luis Mendo's Octave approach might save some bytes? Finally, I'm not 100% sure but is t(apply(x,2,rev)) equivalent to apply(x,1,rev)? \$\endgroup\$ – Giuseppe Jan 21 '18 at 13:22
  • \$\begingroup\$ Thanks, I was able to improve with tip #1 and #3. I did not succeed in saving bytes by adding an argument n to a() to repeat the operation though. \$\endgroup\$ – Florian Jan 21 '18 at 14:02
  • 1
    \$\begingroup\$ I meant something like this \$\endgroup\$ – Giuseppe Jan 21 '18 at 16:49
3
\$\begingroup\$

APL (Dyalog Classic), 8 bytes

(⌽+⍉)⊖+⌽

Try it online!

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

Pari/GP, 31 bytes

a->sum(i=1,4,a=Mat(Vecrev(a))~)

Try it online!

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

JavaScript (ES6), 77 bytes

a=>a.map((b,i)=>b.map((c,j)=>c+a[j][c=l+~i]+a[c][c=l+~j]+a[c][i]),l=a.length)
\$\endgroup\$
2
\$\begingroup\$

Jelly, 7 bytes

ṚZ$3СS

Try it online!

Saved 1 byte thanks to Erik the Outgolfer (also thanks to a suggestion for fixing a bug).

How?

ṚZ$3СS || Full program (monadic).

   3С  || Do this 3 times and collect results in a list
  $     || –> Apply the last two links as a monad
Ṛ       || –––> Reverse,
 Z      || –––> Transpose.
      S || Summation.
\$\endgroup\$
2
\$\begingroup\$

Python 2, 76 bytes

f=lambda x,k=-2:k*x or[map(sum,zip(*r))for r in zip(x,f(zip(*x)[::-1],k+1))]

Try it online!

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

APL (Dyalog Classic), 17 bytes

{⍵+⌽∘⍉⍵+⌽∘⊖⍵+⍉⌽⍵}

Try it online!

APL NARS 34bytes 2117 chars

{⍵+⌽∘⍉⍵+⌽∘⊖⍵+⍉⌽⍵}

-2 chars thanks to ngn

-2 chars because operator composite ∘ seems to have precedence on +

it seems ⌽⍉a rotate a from 90°,⌽⊖a rotate a from 180°,⌽⍉⌽⊖a rotate a from 270° as ⍉⌽

If exist the operator p as:

∇r←(g p)n;a;i;k
   a←⌽,n⋄r←⍬⋄i←0⋄k←⍴a⋄→C
A: →B×⍳r≡⍬⋄r←g¨r
B: r←r,⊂i⊃a
C: →A×⍳k≥i+←1
   r←⌽r
∇

The operator p above would be such that if g is a 1 argument function (monadic?) it should be:

"g f a a a a" is "a ga gga ggga"

the solution would be pheraps 15 chars

  g←{⊃+/⌽∘⍉ p 4⍴⊂⍵}
  a←2 2⍴1 3 2 4
  g a
10 10 
10 10 
  g 1
4

But could be better one operator "composed n time" d such that "3 d f w" is f(f(f(w))).

Now I wrote something but it is too much fragile without the need type checking.

But i like more the operator q that repeat compose of f with argument m (it is not complete because the error cases of the types are not written)

∇r←(n q f)m;i;k;l
   r←⍬⋄k←⍴,n⋄→A×⍳k≤1⋄i←0⋄→D
C: r←r,⊂(i⊃n)q f m
D: →C×⍳k≥i+←1
   →0
A: l←n⋄r←m⋄→0×⍳n≤0
B: l-←1⋄r←f r⋄→B×⍳l≥1
∇

the solution would be 17 chars but i prefer it

  g←{⊃+/(0..3)q(⌽⍉)⍵}
  ⎕fmt g a
┌2─────┐
2 10 10│
│ 10 10│
└~─────┘
  ⎕fmt g 1
4
~
\$\endgroup\$
  • \$\begingroup\$ 270 could be just ⍉⌽ and the whole thing is suitable for a train \$\endgroup\$ – ngn Jan 21 '18 at 16:02
  • \$\begingroup\$ If exist one f such that g f w w w w is w gw ggw gggw the answer would be +/⌽⍉f 4/rho w \$\endgroup\$ – RosLuP Jan 22 '18 at 10:02
  • \$\begingroup\$ You mean +/⌽∘⍉f 4⍴⊂⍵? To get four copies of , first you should enclose it with . To have ⌽⍉ as an operand to f, you must compose it into a single function like this: ⌽∘⍉. The mysterious f could be scan (backslash), but there's another detail to take care of - ⌽∘⍉ will get a left argument, so we must make it ignores it: +/{⌽⍉⍵}\4⍴⊂⍵ or +/⊢∘⌽∘⍉\4⍴⊂⍵. \$\endgroup\$ – ngn Jan 22 '18 at 13:47
  • \$\begingroup\$ In my first comment I was suggesting this train: ⊢ + ⌽∘⍉ + ⌽∘⊖ + ⍉∘⌽. That can lead to even shorter solutions if you rearrange the squiggles cleverly and make good use of trains. \$\endgroup\$ – ngn Jan 22 '18 at 13:49
  • \$\begingroup\$ @ngn even a simple {⍵+ ⍺ }\1 2 3 4 return domain error \$\endgroup\$ – RosLuP Jan 23 '18 at 8:19
2
\$\begingroup\$

K4 / K (oK), 23 8 bytes

Solution:

+/(|+:)\

Try it online!

Example:

+/(|+:)\5 5#14 2 5 10 2 18 9 12 1 9 3 1 5 11 14 13 20 7 19 12 2 1 9 5 6
24 29 31 41 24
41 49 31 49 29
31 31 20 31 31
29 49 31 49 41
24 41 31 29 24

Explanation:

Thanks to ngn for the simplified transformation technique.

+/(|+:)\ / the solution
       \ / converge
  (   )  / function to converge
    +:   / flip
   |     / reverse
+/       / sum over the result

Extra:

In Q this could be written as

sum (reverse flip @) scan
\$\endgroup\$
  • \$\begingroup\$ +/{|+x}\ \$\endgroup\$ – ngn Jan 23 '18 at 3:13
  • \$\begingroup\$ I knew there was a better way to apply the transformations! \$\endgroup\$ – streetster Jan 23 '18 at 7:39
  • \$\begingroup\$ +/(|+:)\ tio.run/##y9bNz/7/X1tfo0bbSjPGWMFY2UjBVMFCwVjB0AhImQGhocH//wA is sadly the same count... Gah cannot figure out markup on mobile. \$\endgroup\$ – streetster Jan 23 '18 at 7:43
  • \$\begingroup\$ It seems markup in comments has a bug, not only on mobile - backslash before backquote messes things up. I avoided it by inserting a space. \$\endgroup\$ – ngn Jan 23 '18 at 12:25
2
\$\begingroup\$

Ruby, 74 72 66 bytes

->a{r=0...a.size;r.map{|i|r.map{|j|(0..3).sum{i,j=j,~i;a[i][j]}}}}

Try it online!

This works on an element-by-element basis, finding the associated elements mathematically, instead of rotating the array. The key part is i,j=j,~i, which turns (i, j) clockwise 90 degrees.

-2 bytes thanks to Mr. Xcoder

-6 bytes because of sum

\$\endgroup\$
1
\$\begingroup\$

Python 3, 105 102 bytes

3 bytes thanks to Mr. Xcoder.

def f(a):l=len(a)-1;r=range(l+1);return[[a[i][j]+a[l-j][i]+a[l-i][l-j]+a[j][l-i]for j in r]for i in r]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Ruby 89 79 bytes

-10 bytes thanks to Unihedron

->m{n=m;3.times{n=n.zip(m=m.transpose.reverse).map{|i,j|i.zip(j).map &:sum}};n}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ I'm pretty sure you can replace .map &:dup with *1 to cut off a lot of characters. array*length creates a new array and is a handy way to shallow clone. \$\endgroup\$ – Unihedron Jan 20 '18 at 13:35
  • \$\begingroup\$ Actually, n=*m is even shorter. \$\endgroup\$ – Unihedron Jan 20 '18 at 13:41
  • \$\begingroup\$ @Unihedron that's the problem, I need to deep clone \$\endgroup\$ – Asone Tuhid Jan 20 '18 at 14:17
  • \$\begingroup\$ Seems to me that it doesn't affect the output; I fiddled with it in your "try it online" link and the output appears to remain correct with that change \$\endgroup\$ – Unihedron Jan 20 '18 at 14:31
  • \$\begingroup\$ You're right, actually you don't even need a shallow clone, transpose takes care of that \$\endgroup\$ – Asone Tuhid Jan 20 '18 at 15:36
1
\$\begingroup\$

05AB1E, 12 bytes

3FÂø}3F‚øε`+

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Haskell, 84 83 67 bytes

z=zipWith
e=[]:e
f l=foldr(\_->z(z(+))l.foldr(z(:).reverse)e)l"123"

Try it online!

Thanks to Laikoni and totallyhuman for saving a lot of bytes!

\$\endgroup\$
1
\$\begingroup\$

Husk, 9 bytes

F‡+↑4¡(↔T

Try it online!

Explanation

F‡+↑4¡(↔T)  -- implicit input M, for example: [[1,0,1],[2,3,4],[0,0,2]]
     ¡(  )  -- repeat infinitely times starting with M  
        T   -- | transpose: [[1,2,0],[0,3,0],[1,4,2]]
       ↔    -- | reverse: [[1,4,2],[0,3,0],[1,2,0]]
            -- : [[[1,0,1],[2,3,4],[0,0,2]],[[1,4,2],[0,3,0],[1,2,0]],[[2,0,0],[4,3,2],[1,0,1]],[[0,2,1],[0,3,0],[2,4,1]],[[1,0,1],[2,3,4],[0,0,2]],…
   ↑4       -- take 4: [[[1,0,1],[2,3,4],[0,0,2]],[[1,4,2],[0,3,0],[1,2,0]],[[2,0,0],[4,3,2],[1,0,1]],[[0,2,1],[0,3,0],[2,4,1]]]
F           -- fold (reduce) the elements (example with [[1,0,1],[2,3,4],[0,0,2]] [[1,4,2],[0,3,0],[1,2,0]])
 ‡+         -- | deep-zip addition (elementwise addition): [[2,4,3],[2,6,4],[1,2,2]]
            -- : [[4,6,4],[6,12,6],[4,6,4]]
\$\endgroup\$
1
\$\begingroup\$

tinylisp, 132 bytes

Let's take the recently added library function transpose for a spin!

(load library
(d T transpose
(d R(q((m #)(i #(c m(R(reverse(T m))(dec #)))(
(q((m)(foldl(q(p(map(q((r)(map sum(T r))))(T p))))(R m 4

The last line is an unnamed lambda function that performs rotation summation. To actually use it, you'll want to use d to bind it to a name. Try it online!

Ungolfed, with comments

(load library) (comment Get functions from the standard library)

(comment Rotating a matrix by 90 degrees is just transpose + reverse)
(def rotate
 (lambda (matrix)
  (reverse (transpose matrix))))

(comment This function recursively generates a list of (count) successive rotations
          of (matrix))
(def rotations
 (lambda (matrix count)
  (if count
   (cons matrix
    (rotations (rotate matrix) (dec count)))
   nil)))

(comment To add two matrices, we zip them together and add the pairs of rows)
(def matrix-add
 (lambda two-matrices
  (map row-sum (transpose two-matrices))))

(comment To add two rows of a matrix, we zip them together and add the pairs of numbers)
(def row-sum
 (lambda (two-rows)
  (map sum (transpose two-rows))))

(comment Our final function: generate a list containing four rotations of the argument
          and fold them using matrix-add)
(def rotated-sum
 (lambda (matrix)
  (foldl matrix-add (rotations matrix 4))))
\$\endgroup\$
1
\$\begingroup\$

Attache, 20 bytes

Sum@MatrixRotate&0:3

Try it online!

Explanation

Sum@MatrixRotate&0:3

MatrixRotate&0:3 expands to, with input x, MatrixRotate[x, 0:3], which in turn exapnds to [MatrixRotate[x, 0], MatrixRotate[x, 1], MatrixRotate[x, 2], MatrixRotate[x, 3]]. That is to say, it vectorizes over the RHS. Then, Sum takes the sum of all of these matrices by one level. This gives the desired result.

\$\endgroup\$
1
\$\begingroup\$

Java 8, 135 bytes

a->{int l=a.length,r[][]=new int[l][l],i=0,j;for(;i<l;i++)for(j=0;j<l;)r[i][j]=a[i][j]+a[j][l+~i]+a[l+~i][l+~j]+a[l+~j++][i];return r;}

Explanation:

Try it online.

a->{                        // Method with integer-matrix as both parameter and return-type
  int l=a.length,           //  Dimensions of the input-matrix
      r[][]=new int[l][l],  //  Result-matrix of same size
      i=0,j;                //  Index-integers
  for(;i<l;i++)             //  Loop over the rows
    for(j=0;j<l;)           //   Loop over the columns
      r[i][j]=              //    Set the cell of the result-matrix to:
              a[i][j]+a[j][l+~i]+a[l+~i][l+~j]+a[l+~j++][i];
                            //     The four linked cells of the input-matrix
  return r;}                //  Return the result-matrix
\$\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.