Sum the diagonals

19

0

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.

Stewie Griffin

Posted 2017-05-11T21:27:36.377

Reputation: 43 471

Related – nimi – 2017-05-11T21:44:24.840

Answers

6

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.

Greg Martin

Posted 2017-05-11T21:27:36.377

Reputation: 13 940

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))& – Martin Ender – 2017-05-13T09:53:49.727

6

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.

Laikoni

Posted 2017-05-11T21:27:36.377

Reputation: 23 676

That's shorter point-free: foldl1$(.(++z)).zipWith(+).(0:). – Ørjan Johansen – 2017-05-11T23:36:56.747

5

JavaScript (ES6), 65 58 bytes

a=>a.map(b=>b.map((c,i)=>r[i]=~~r[i]+c,r=[,...r]),r=[])&&r

Neil

Posted 2017-05-11T21:27:36.377

Reputation: 95 035

63-byte variant: a=>a.map(r=>r.map(v=>s[i]=~~s[i++]+v,i=--y),s=[],y=a.length)&&s – Arnauld – 2017-05-13T09:57:04.200

@Arnauld I agree, reversing was a bad move. But taking the length is too long too! – Neil – 2017-05-13T10:04:59.777

5

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

Luis Mendo

Posted 2017-05-11T21:27:36.377

Reputation: 87 464

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? – Stewie Griffin – 2017-05-12T08:43:03.440

@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 – Luis Mendo – 2017-05-12T08:59:51.787

5

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.

Dennis

Posted 2017-05-11T21:27:36.377

Reputation: 196 637

Only the first R to reduce has one less element; it increases by one more element each row. – Ørjan Johansen – 2017-05-12T03:39:53.780

This is just clever... no ŒD? – Erik the Outgolfer – 2017-05-13T10:07:54.097

@EriktheOutgolfer Once again, ŒD's weird ordering prevented it from being useful. – Dennis – 2017-05-13T15:47:56.513

@Dennis Then I think I'd make something that doesn't have so weird ordering... oh, maybe 3 monads might be incoming. – Erik the Outgolfer – 2017-05-13T15:54:12.947

3

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

Business Cat

Posted 2017-05-11T21:27:36.377

Reputation: 8 927

2

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)

Emigna

Posted 2017-05-11T21:27:36.377

Reputation: 50 798

2

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.

Conor O'Brien

Posted 2017-05-11T21:27:36.377

Reputation: 36 228

2

Python 2, 62 bytes

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

Try it online!

Dennis

Posted 2017-05-11T21:27:36.377

Reputation: 196 637

1

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

Jonathan Allan

Posted 2017-05-11T21:27:36.377

Reputation: 67 804

1

Perl 5, 47 bytes

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

faubi

Posted 2017-05-11T21:27:36.377

Reputation: 2 599

1

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.

Billywob

Posted 2017-05-11T21:27:36.377

Reputation: 3 363

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! – Giuseppe – 2017-05-12T18:06:33.300

1

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

It Guy

Posted 2017-05-11T21:27:36.377

Reputation: 61

1[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! =) – Stewie Griffin – 2017-05-13T09:31:22.487

Also, zeros(m-1,m) can be written ~e(m-1,m), saving 4 bytes :) Neat huh? – Stewie Griffin – 2017-05-13T10:20:16.653

0

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).

HyperNeutrino

Posted 2017-05-11T21:27:36.377

Reputation: 26 575

0

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);}

Khaled.K

Posted 2017-05-11T21:27:36.377

Reputation: 1 435

0

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!

Jörg Hülsermann

Posted 2017-05-11T21:27:36.377

Reputation: 13 026

0

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.

Kevin

Posted 2017-05-11T21:27:36.377

Reputation: 501

0

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

Titus

Posted 2017-05-11T21:27:36.377

Reputation: 13 814

0

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.

NikoNyrh

Posted 2017-05-11T21:27:36.377

Reputation: 2 361

0

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}]

J42161217

Posted 2017-05-11T21:27:36.377

Reputation: 15 931