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 code-golf, so the shortest submission in each language wins.
-
\$\begingroup\$ Related \$\endgroup\$nimi– nimi2017年05月11日 21:44:24 +00:00Commented May 11, 2017 at 21:44
22 Answers 22
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.
-
\$\begingroup\$ That's shorter point-free:
foldl1$(.(++z)).zipWith(+).(0:). \$\endgroup\$Ørjan Johansen– Ørjan Johansen2017年05月11日 23:36:56 +00:00Commented May 11, 2017 at 23:36
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.
-
\$\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– Martin Ender2017年05月13日 09:53:49 +00:00Commented May 13, 2017 at 9:53
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
-
\$\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– Stewie Griffin2017年05月12日 08:43:03 +00:00Commented May 12, 2017 at 8:43 -
\$\begingroup\$ @StewieGriffin I have sometimes thought about that. My doubt was more between
sum(x)andsum(x,1). For a matrixx, the fact thatsum(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 somefun(x,1)functions for the most common cases \$\endgroup\$Luis Mendo– Luis Mendo2017年05月12日 08:59:51 +00:00Commented May 12, 2017 at 8:59
Jelly, 5 bytes
0;+μ/
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.
-
\$\begingroup\$ Only the first R to reduce has one less element; it increases by one more element each row. \$\endgroup\$Ørjan Johansen– Ørjan Johansen2017年05月12日 03:39:53 +00:00Commented May 12, 2017 at 3:39
-
\$\begingroup\$ This is just clever... no
ŒD? \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2017年05月13日 10:07:54 +00:00Commented May 13, 2017 at 10:07 -
\$\begingroup\$ @EriktheOutgolfer Once again,
ŒD's weird ordering prevented it from being useful. \$\endgroup\$Dennis– Dennis2017年05月13日 15:47:56 +00:00Commented May 13, 2017 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– Erik the Outgolfer2017年05月13日 15:54:12 +00:00Commented May 13, 2017 at 15:54
JavaScript (ES6), (削除) 65 (削除ここまで) 58 bytes
a=>a.map(b=>b.map((c,i)=>r[i]=~~r[i]+c,r=[,...r]),r=[])&&r
-
\$\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– Arnauld2017年05月13日 09:57:04 +00:00Commented May 13, 2017 at 9:57 -
\$\begingroup\$ @Arnauld I agree, reversing was a bad move. But taking the length is too long too! \$\endgroup\$Neil– Neil2017年05月13日 10:04:59 +00:00Commented May 13, 2017 at 10:04
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.
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
05AB1E, 17 bytes
Rvy1gÅ0«NFÁ}})øO ̈
Explanation
R # reverse input
v # for each N,y (index, item)
y1gÅ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)
J, 7 bytes
+//.@|.
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.
Jelly, 8 bytes
ŒDS€ṙZL$
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
Perl 5, 47 bytes
map{$j=--$.;map{@a[$j++]+=$_}split}<>
print"@a"
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.
-
\$\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– Giuseppe2017年05月12日 18:06:33 +00:00Commented May 12, 2017 at 18:06
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
-
1\$\begingroup\$
[m,n]=size(A);for i=1:m+n-1,trace([zeros(m-1,m);A'](i:end,:)),endsaves 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 useinput, like this bringing it back up to 75 bytes. Nice approach though, so +1 from me :) And welcome to PPCG! =) \$\endgroup\$Stewie Griffin– Stewie Griffin2017年05月13日 09:31:22 +00:00Commented May 13, 2017 at 9:31 -
\$\begingroup\$ Also,
zeros(m-1,m)can be written~e(m-1,m), saving 4 bytes :) Neat huh? \$\endgroup\$Stewie Griffin– Stewie Griffin2017年05月13日 10:20:16 +00:00Commented May 13, 2017 at 10:20
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).
-
\$\begingroup\$ I get an error for the last test case. tio.run/nexus/… \$\endgroup\$Dennis– Dennis2017年05月12日 07:50:38 +00:00Commented May 12, 2017 at 7:50
C, 148 bytes
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);}
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);
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.
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
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.
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}]
Husk, 6 bytes
mΣ∂m↔T
Explanation:
T # Transpose the (implicit) argument; swapping rows/columns
m↔ # Reverse each row
∂ # Take the anti-diagonals of this matrix
mΣ # And sum each inner anti-diagonal list
# (after which the result is output implicitly)