19
\$\begingroup\$

Take a matrix of positive integers as input, and output the individual sums of the elements on the diagonal lines through the matrix.

You shall only count the lines that goes diagonally down and to the right. You must start with the diagonal that contains only the bottom-left element, then the length-two diagonal above that (if it exists) and so on through to the diagonal that contains only the top-right element, as illustrated below.

Example:

Input:
 8   14    5    1
10    5    5    8
 6    6    8   10
15   15    4   11

Output:
15, 21, 20, 32, 29, 13, 1
(Diagonals: {{15},{6,15},{10,6,4},{8,5,8,11},{14,5,10},{5,8},{1}})

Input:
1
Output:
1

Input: 
1 5
Output:
1, 5

Input:
4
1

Output: 
1, 4

Input:
17    4    5
24   16    5
 9   24   10
 1   14   22
 1   21   24
 4    4   17
24   25   17

Output:
24, 29, 22, 39, 47, 70, 43, 9, 5

Input and output formats are optional as always.

This is , so the shortest submission in each language wins.

\$\endgroup\$
  • \$\begingroup\$ Related \$\endgroup\$ – nimi May 11 '17 at 21:44

20 Answers 20

6
\$\begingroup\$

Haskell, 40 37 bytes

z=0:z
foldl1$(.(++z)).zipWith(+).(0:)

Try it online! Usage: (foldl1$(.(++z)).zipWith(+).(0:)) [[1,2,3],[4,5,6]].

Edit: Thanks to Ørjan Johansen for -3 bytes!

Ungolfed:

z = 0:z
s#t = zipWith(+)(0:s)(t++z)
f m = foldl1 (#) m

z is a list of infinitely many zeros. In f we fold over the list of lists m by combining two lists with the function #. In # the first list s contains the accumulated column sums so far and the second list t is the new row which should be added. We shift s one element to the right by adding a zero to the front and element-wise add s and t with zipWith(+). Because s might be arbitrarily large, we have to pad t with enough zeros by appending z.

\$\endgroup\$
  • \$\begingroup\$ That's shorter point-free: foldl1$(.(++z)).zipWith(+).(0:). \$\endgroup\$ – Ørjan Johansen May 11 '17 at 23:36
6
\$\begingroup\$

Mathematica, 53 54 bytes

l=Length@#-1&;Tr@Diagonal[#,k]~Table~{k,-l@#,l@#&@@#}&

Pure function taking a 2D-array as input and returning a list. (Entries don't have to be integers or even numbers.) Diagonal[#,k] returns the kth diagonal above (or below, if k is negative) the main diagonal. {k,-l@#,l@#&@@#} computes the range of diagonals needed based on the dimensions of the input array. And Tr sums the entries of each diagonal.

\$\endgroup\$
  • \$\begingroup\$ Alternative at the same byte count, but maybe you can golf it further? Those parentheses look bad. Tr@Diagonal[m,#]&/@Range@@({-1,1}(Dimensions[m=#]-1))& \$\endgroup\$ – Martin Ender May 13 '17 at 9:53
5
\$\begingroup\$

MATL, 6 bytes

T&XdXs

Try it online! Or verify all test cases.

Explanation

T&Xd   % All diagonals of implicit input arranged as zero-padded columns
Xs     % Sum of each column. Implicitly display
\$\endgroup\$
  • \$\begingroup\$ Just curious: Do you think it would be better overall to have s==sum(x(:)), instead of sticking to the MATLAB convention, as MATL seems to do? \$\endgroup\$ – Stewie Griffin May 12 '17 at 8:43
  • \$\begingroup\$ @StewieGriffin I have sometimes thought about that. My doubt was more between sum(x) and sum(x,1). For a matrix x, the fact that sum(x) behaves differently if the matrix has 1 row is sometimes annoying. But in the end I decided to go with Matlab, so the two languages are closer; and add some fun(x,1) functions for the most common cases \$\endgroup\$ – Luis Mendo May 12 '17 at 8:59
5
\$\begingroup\$

Jelly, 5 bytes

0;+µ/

Try it online!

How it works

0;+µ/  Main link. Argument: M (matrix / array of rows)

   µ   Combine all links to the left into a chain (arity unknown at parse time) and
       begin a new monadic chain.
    /  Reduce M by that chain. This makes the chain dyadic.
       Let's call the arguments of the chain L and R (both flat arrays).
0;         Prepend a 0 to L.
  +        Perform element-wise addition of the result and R.
           When the chain is called for the n-th time, R has n less elements, so
           the last n elements of L won't have matching elements in R and will be
           left unaltered.
\$\endgroup\$
  • \$\begingroup\$ Only the first R to reduce has one less element; it increases by one more element each row. \$\endgroup\$ – Ørjan Johansen May 12 '17 at 3:39
  • \$\begingroup\$ This is just clever... no ŒD? \$\endgroup\$ – Erik the Outgolfer May 13 '17 at 10:07
  • \$\begingroup\$ @EriktheOutgolfer Once again, ŒD's weird ordering prevented it from being useful. \$\endgroup\$ – Dennis May 13 '17 at 15:47
  • \$\begingroup\$ @Dennis Then I think I'd make something that doesn't have so weird ordering... oh, maybe 3 monads might be incoming. \$\endgroup\$ – Erik the Outgolfer May 13 '17 at 15:54
5
\$\begingroup\$

JavaScript (ES6), 65 58 bytes

a=>a.map(b=>b.map((c,i)=>r[i]=~~r[i]+c,r=[,...r]),r=[])&&r
\$\endgroup\$
  • \$\begingroup\$ 63-byte variant: a=>a.map(r=>r.map(v=>s[i]=~~s[i++]+v,i=--y),s=[],y=a.length)&&s \$\endgroup\$ – Arnauld May 13 '17 at 9:57
  • \$\begingroup\$ @Arnauld I agree, reversing was a bad move. But taking the length is too long too! \$\endgroup\$ – Neil May 13 '17 at 10:04
3
\$\begingroup\$

CJam, 22 21 bytes

Saved 1 byte thanks to Martin Ender

{_,({0\f+}*ee::m<:.+}

Anonymous block expecting the argument on the stack and leaves the result on the stack.

Try it online!

How it works

_                   e# Duplicate the matrix
 ,(                 e# Get its length (# of rows) minus 1
   {0\f+}*          e# Prepend that many 0s to each row
          ee        e# Enumerate; map each row to [index, row]
            ::m<    e# Rotate each row left a number of spaces equal to its index
                :.+ e# Sum each column
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 17 bytes

Rvy¹gÅ0«NFÁ}})øO¨

Try it online!

Explanation

R                  # reverse input
 v                 # for each N,y (index, item)
  y¹gÅ0«           # pad y with as many zeroes as the number of rows in the input
        NFÁ}       # rotate each row N times right
            })     # wrap the result in a list
              øO   # sum the columns
                ¨  # remove the last element of the resulting list (the padded zeroes)
\$\endgroup\$
2
\$\begingroup\$

J, 7 bytes

+//.@|.

Try it online!

This is pretty simple:

+//.@|.
+/        sum
  /.      on oblique lines
    @|.   on the reversed array

Oblique reversed lines are the diagonals of the array, so this is just summing the diagonals.

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

Python 2, 62 bytes

lambda M:reduce(lambda x,y:map(sum,zip([0]+x,y+[0]*len(x))),M)

Try it online!

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

Jelly, 8 bytes

ŒDS€ṙZL$

Try it online!

Half of the code is used to put the results into the correct order.

How?

ŒDS€ṙZL$ - Main link: list of lists of numbers
ŒD       - diagonals (starts with the diagonal containing the top left element,
         -            then the next diagonal to the right, and so on wrapping around)
  S€     - sum €each
       $ - last two links as a monad
     Z   - transpose the matrix
      L  - length (width of the matrix)
    ṙ    - rotate the results left by that amount
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 47 bytes

map{$j=--$.;map{@a[$j++]+=$_}split}<>
print"@a"
\$\endgroup\$
1
\$\begingroup\$

R, 45 bytes

Unnamed function taking a matrix-class object as input:

function(x)sapply(split(x,col(x)-row(x)),sum)

Using the idea explained in this answer.

\$\endgroup\$
  • \$\begingroup\$ I believe the rules in this challenge allow for you to get rid of the call to unname, but this is an awesome solution regardless! \$\endgroup\$ – Giuseppe May 12 '17 at 18:06
1
\$\begingroup\$

Octave, 71 bytes

Assuming A is a matrix, for example:

A = [17 4 5;24 16 5; 9 24 10; 1 14 22; 1 21 24; 4 4 17;24 25 17];

Then we have:

[m,n]=size(A);
a=[zeros(m,m-1),A]';
for i=1:m+n-1
trace(a(i:end,:))
end

Notice that transposing the matrix reverses the ordering of the diagonal sums, which saved an overall two bytes in the for loop.

Output:

ans =  24
ans =  29
ans =  22
ans =  39
ans =  47
ans =  70
ans =  43
ans =  9
ans =  5
\$\endgroup\$
  • 1
    \$\begingroup\$ [m,n]=size(A);for i=1:m+n-1,trace([zeros(m-1,m);A'](i:end,:)),end saves 6 bytes. Octave can do direct indexing and inline assignments. Unfortunately, assuming that a variable exist in the work space prior to running the code is not allowed, so I think you must use input, like this bringing it back up to 75 bytes. Nice approach though, so +1 from me :) And welcome to PPCG! =) \$\endgroup\$ – Stewie Griffin May 13 '17 at 9:31
  • \$\begingroup\$ Also, zeros(m-1,m) can be written ~e(m-1,m), saving 4 bytes :) Neat huh? \$\endgroup\$ – Stewie Griffin May 13 '17 at 10:20
0
\$\begingroup\$

Python, 126 bytes

x=input()
f=lambda k:[x[i+k][i]for i in range(len(x)-k)]
a=map(f,range(4)[::-1])
x=zip(*x)
print(map(sum,a+map(f,range(1,4))))

f only works on the lower triangular section, so I transpose it and get the upper triangular section that way. Don't know why the f function doesn't work for negative values (I changed f to be shorter because the part to get the negatives didn't work).

\$\endgroup\$
  • \$\begingroup\$ I get an error for the last test case. tio.run/nexus/… \$\endgroup\$ – Dennis May 12 '17 at 7:50
0
\$\begingroup\$

C, 148 bytes

Try Online

s;g(int i,int j,int**m,int x){for(s=0;x;x--)s+=m[i++][j++];printf(" %d",s);}
k;f(int n,int**m){for(k=n;--k;)g(k,0,m,n-k);for(;k<n;k++)g(0,k,m,n-k);}
\$\endgroup\$
0
\$\begingroup\$

PHP, 81 Bytes

Take Input as 2 D Array

<?foreach($_GET as$k=>$v)foreach($v as$x=>$y)$r[$x-$k]+=$y;ksort($r);print_r($r);

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Awk, 67 Bytes

{for(f=0;f++<NF;)s[NF-NR+f]+=$f}END{i=0;while(i++<NR*2)print s[i]}

Ungolfed:

{
    for (f = 0; f++ < NF;)
        s[NF-NR+f] += $f
}
END {
    i = 0
    while (i++ < NR*2)
        print s[i]
}

Awk splits on whitespace $n is the nth field (1-indexed); NF is the number of fields on the line, NR is the number of the current row. Undefined variables are 0 and created on first use.

\$\endgroup\$
0
\$\begingroup\$

PHP, 86 bytes

a memory friendly solution in two variants:

<?for($i=$c=count($a=$_GET);--$i>-$c;print$s._)for($s=0,$d=$c;$d--;)$s+=$a[$i+$d][$d];
<?for($i=$c=count($a=$_GET);--$i>-$c;print$s._)for($s=$d=0;$d<$c;)$s+=$a[$i+$d][$d++];

takes input from script parameters, uses underscore as delimiter;
use default settings (not default php.ini) or try them online

\$\endgroup\$
0
\$\begingroup\$

Clojure, 81 bytes

#(apply map +(map(fn[i c](concat(repeat(-(count %)i 1)0)c(repeat i 0)))(range)%))

Quite verbose, as it pads lists with zeros so that we can just calculate the column-wise sum.

\$\endgroup\$
0
\$\begingroup\$

mathematica 73 bytes

Plus@@@Table[Diagonal[Partition[#1,#2[[1]]],k],{k,-#2[[2]]+1,#2[[1]]-1}]&

This one works for ANY 2D-array m x n (not only nxn)
input the array at the end of the code like this (the last test case)

[{17,4,5,24,16,5,9,24,10,1,14,22,1,21,24,4,4,17,24,25,17},{3,7}]

{24, 29, 22, 39, 47, 70, 43, 9, 5}

input in form [{a,b,c,d...},{m,n}]

\$\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.