Inspired by this.
Agatha Stephendale, a sophomore who is really into raster graphics, has taken a course in linear algebra. Now she imagines matrices as rectangles, but in her artistic mind, she attaches diagonal lines to those rectangles and tries to compute traces along them. In fact, she wants to compute traces of all matrices, not just square ones.
Since Agatha is an artist, she knows how to draw lines in her favourite image editor, and the latter uses Bresenham’s algorithm to plot lines. She even checked Wikipedia and found the pseudocode:
function line(x0, y0, x1, y1)
real deltax := x1 - x0
real deltay := y1 - y0
real deltaerr := abs(deltay / deltax) // Assume deltax != 0 (line is not vertical),
// note that this division needs to be done in a way that preserves the fractional part
real error := 0.0 // No error at start
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
while error ≥ 0.5 then
y := y + sign(deltay) * 1
error := error - 1.0
(Note that this pseudocode works only for slopes less than 1; for tall grids, a similar treatment should be done, but with a loop over y
. See this section for the two cases.)
Agatha imagines a matrix as a rectangle, draws a diagonal line in it, and Bresenham’s algorithm determines which elements of a matrix belong to the diagonal. Then she takes their sum, and this is what she wants to implement in as few bytes as possible because she is a poor student and cannot afford large-capacity HDDs to store her code.
Task
Given a matrix A, return the sum of the elements that lie on the rasterised main diagonal (from top left to bottom right), where the latter is determined by Bresenham’s line algorithm. That is, assuming that the matrix represents a m×n grid, draw a line on that grid from A[1, 1] to A[m, n] using Bresenham’s algorithm, and take the sum of all elements on the line. Note that for 1×N and N×1 matrices, the entire matrix becomes its own diagonal (because this is how one would draw a line from the first element of the first row to the last element of the last row).
Input: a real matrix (may be a 1×1 matrix, a row matrix, a column matrix, or a rectangular matrix). Output: a number.
Note that some sources (e. g. the Wikipedia’s pseudocode above) use the condition check error≥0.5
, while other sources use error>0.5
. You should use the originally posted one (error≥0.5
), but if the alternative error>0.5
is shorter in your code, then you are allowed to implement it (since this is code golf), but mention it explicitly. See test case 4.
Challenge rules
- I/O formats are flexible. A matrix can be several lines of space-delimited numbers separated by newlines, or an array of row vectors, or an array of column vectors etc.
- This is code-golf, so shortest answer in bytes wins.
- Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs.
- Default loopholes are forbidden.
Test cases
[[1,2,3],[4,5,6],[7,8,9]]
→1+5+9
→ output:15
.
[[1,2,3,4],[5,6,7,8]]
→1+2+7+8
→ output:18
.
[[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24]]
→1+8+9+16+17+24
→ output:75
.
[[1,2,3,4,5],[6,7,8,9,10]]
→1+2+8+9+10
(using the≥
error condition) → output:30
.
However, if it would be shorter to use the strict inequality >
in your code, then the allowed output is 1+2+3+9+10=25
, but you should mention it separately.
[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
→1+5+8+12
→ output:26
.
[[-0.3,0.5]]
→ output:0.2
.[[3.1],[2.9]]
→ output:6
.[[-5]]
→ output:-5
.
More information on Bresenham’s algorithm
- http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm — a collection of algorithms for different languages;
- https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html — a nice explanation featuring different cases for slopes;
- https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm;
[[1,2,3,4,5],[6,7,8,9,10]]
. \$\endgroup\$[[1,2],[3,4],[5,6],[7,8],[9,10]]
\$\endgroup\$28
(with≥
, the expected implementation) or 27 (with>
, the optional implementation.) \$\endgroup\$