Sum of elements below main diagonal of matrix

From Rosetta Code
Revision as of 15:55, 10 October 2021 by ReeceGoding (talk | contribs) (Added R.)
Sum of elements below main diagonal of matrix is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Find and display the sum of elements that are below the main diagonal of a matrix.

The matrix should be a square matrix.


───   Matrix to be used:   ───

     [[1,3,7,8,10],
      [2,4,16,14,4],
      [3,1,9,18,11],
      [12,14,17,18,20],
      [7,1,3,9,5]] 



ALGOL 68

<lang algol68>BEGIN # sum the elements below the main diagonal of a matrix #

   # returns the sum of the elements below the main diagonal #
   # of m, m must be a square matrix                         #
   OP   LOWERSUM = ( [,]INT m )INT:
        IF 1 LWB m /= 2 LWB m OR 1 UPB m /= 2 UPB m THEN
           # the matrix isn't square                         #
           print( ( "Matrix must be suare for LOWERSUM", newline ) );
           stop
        ELSE
           # have a square matrix                            #
           INT sum := 0;
           FOR r FROM 1 LWB m + 1 TO 1 UPB m DO
                FOR c FROM 1 LWB m TO r - 1 DO
                    sum +:= m[ r, c ]
                OD
           OD;
           sum
        FI; # LOWERSUM #
   # task test case                                          #
   print( ( whole( LOWERSUM [,]INT( (  1,  3,  7,  8, 10 )
                                  , (  2,  4, 16, 14,  4 )
                                  , (  3,  1,  9, 18, 11 )
                                  , ( 12, 14, 17, 18, 20 )
                                  , (  7,  1,  3,  9,  5 )
                                  )
                 , 0
                 )
           , newline
           )
         )

END</lang>

Output:
69

ALGOL W

One of the rare occasions where the lack of lower/upper bound operators in Algol W actually simplifies things, assuming the programmer gets things right... <lang algolw>begin % sum the elements below the main diagonal of a matrix  %

   % returns the sum of the elements below the main diagonal %
   % of m, m must have bounds lb :: ub, lb :: ub             %
   integer procedure lowerSum ( integer array m ( *, * )
                              ; integer value lb, ub
                              ) ;
   begin
       integer sum;
       sum := 0;
       for r := lb + 1 until ub do begin
            for c := lb until r - 1 do sum := sum + m( r, c )
       end for_r;
       sum
   end lowerSum ;
   begin % task test case                                    %
       integer array m ( 1 :: 5, 1 :: 5 );
       integer r, c;
       r := 1; c := 0; for v :=  1,  3,  7,  8, 10 do begin c := c + 1; m( r, c ) := v end;
       r := 2; c := 0; for v :=  2,  4, 16, 14,  4 do begin c := c + 1; m( r, c ) := v end;
       r := 3; c := 0; for v :=  3,  1,  9, 18, 11 do begin c := c + 1; m( r, c ) := v end;
       r := 4; c := 0; for v := 12, 14, 17, 18, 20 do begin c := c + 1; m( r, c ) := v end;
       r := 5; c := 0; for v :=  7,  1,  3,  9,  5 do begin c := c + 1; m( r, c ) := v end;
       write( i_w := 1, lowerSum( m, 1, 5 ) )
   end

end.</lang>

Output:
69

APL

Works with: Dyalog APL

<lang apl>sum_below_diagonal ← +/(∊⊢×(>/¨⍳∘⍴))</lang>

Output:
      matrix ← 5 5⍴1 3 7 8 10 2 4 16 14 4 3 1 9 18 11 12 14 17 18 20 7 1 3 9 5
      sum_below_diagonal matrix
69

AutoHotkey

<lang AutoHotkey>matrx :=[[1,3,7,8,10] ,[2,4,16,14,4] ,[3,1,9,18,11] ,[12,14,17,18,20] ,[7,1,3,9,5]] sumA := sumB := sumD := sumAll := 0 for r, obj in matrx for c, val in obj sumAll += val ,sumA += r<c ? val : 0 ,sumB += r>c ? val : 0 ,sumD += r=c ? val : 0

MsgBox % result := "sum above diagonal = " sumA . "`nsum below diagonal = " sumB . "`nsum on diagonal = " sumD . "`nsum all = " sumAll</lang>

Output:
sum above diagonal = 111
sum below diagonal = 69
sum on diagonal = 37
sum all = 217

AWK

<lang AWK>

  1. syntax: GAWK -f SUM_OF_ELEMENTS_BELOW_MAIN_DIAGONAL_OF_MATRIX.AWK

BEGIN {

   arr1[++n] = "1,3,7,8,10"
   arr1[++n] = "2,4,16,14,4"
   arr1[++n] = "3,1,9,18,11"
   arr1[++n] = "12,14,17,18,20"
   arr1[++n] = "7,1,3,9,5"
   for (i=1; i<=n; i++) {
     x = split(arr1[i],arr2,",")
     if (x != n) {
       printf("error: row %d has %d elements; S/B %d\n",i,x,n)
       errors++
       continue
     }
     for (j=1; j<i; j++) { # below main diagonal
       sum_b += arr2[j]
       cnt_b++
     }
     for (j=i+1; j<=n; j++) { # above main diagonal
       sum_a += arr2[j]
       cnt_a++
     }
     for (j=1; j<=i; j++) { # on main diagonal
       if (j == i) {
         sum_o += arr2[j]
         cnt_o++
       }
     }
   }
   if (errors > 0) { exit(1) }
   printf("%5g Sum of the %d elements below main diagonal\n",sum_b,cnt_b)
   printf("%5g Sum of the %d elements above main diagonal\n",sum_a,cnt_a)
   printf("%5g Sum of the %d elements on main diagonal\n",sum_o,cnt_o)
   printf("%5g Sum of the %d elements in the matrix\n",sum_b+sum_a+sum_o,cnt_b+cnt_a+cnt_o)
   exit(0)

} </lang>

Output:
   69 Sum of the 10 elements below main diagonal
  111 Sum of the 10 elements above main diagonal
   37 Sum of the 5 elements on main diagonal
  217 Sum of the 25 elements in the matrix

C

Interactive program which reads the matrix from a file : <lang C>

  1. include<stdlib.h>
  2. include<stdio.h>

typedef struct{ int rows,cols; int** dataSet; }matrix;

matrix readMatrix(char* dataFile){ FILE* fp = fopen(dataFile,"r"); matrix rosetta; int i,j;

fscanf(fp,"%d%d",&rosetta.rows,&rosetta.cols);

rosetta.dataSet = (int**)malloc(rosetta.rows*sizeof(int*));

for(i=0;i<rosetta.rows;i++){ rosetta.dataSet[i] = (int*)malloc(rosetta.cols*sizeof(int)); for(j=0;j<rosetta.cols;j++) fscanf(fp,"%d",&rosetta.dataSet[i][j]); }

fclose(fp); return rosetta; }

void printMatrix(matrix rosetta){ int i,j;

for(i=0;i<rosetta.rows;i++){ printf("\n"); for(j=0;j<rosetta.cols;j++) printf("%3d",rosetta.dataSet[i][j]); } }

int findSum(matrix rosetta){ int i,j,sum = 0;

for(i=1;i<rosetta.rows;i++){ for(j=0;j<i;j++){ sum += rosetta.dataSet[i][j]; } }

return sum; }

int main(int argC,char* argV[]) { if(argC!=2) return printf("Usage : %s <filename>",argV[0]);

matrix data = readMatrix(argV[1]);

printf("\n\nMatrix is : \n\n"); printMatrix(data);

printf("\n\nSum below main diagonal : %d",findSum(data));

return 0; } </lang>

Input Data file, first row specifies rows and columns :

5 5
1 3 7 8 10
2 4 16 14 4
3 1 9 18 11
12 14 17 18 20
7 1 3 9 5

And output follows :

Output:
C:\My Projects\BGI>a.exe rosettaData.txt


Matrix is :


  1  3  7  8 10
  2  4 16 14  4
  3  1  9 18 11
 12 14 17 18 20
  7  1  3  9  5

Sum below main diagonal : 69

C++

<lang cpp>#include <iostream>

  1. include <vector>

template<typename T> T sum_below_diagonal(const std::vector<std::vector<T>>& matrix) {

   T sum = 0;
   for (std::size_t y = 0; y < matrix.size(); y++)
       for (std::size_t x = 0; x < matrix[y].size() && x < y; x++)
           sum += matrix[y][x];
   return sum;

}

int main() {

   std::vector<std::vector<int>> matrix = {
       {1,3,7,8,10},
       {2,4,16,14,4},
       {3,1,9,18,11},
       {12,14,17,18,20},
       {7,1,3,9,5}
   };
   
   std::cout << sum_below_diagonal(matrix) << std::endl;
   return 0;

}</lang>

Output:
69

Excel

LAMBDA

Binding the name matrixTriangle to the following lambda expression in the Name Manager of the Excel WorkBook:

(See LAMBDA: The ultimate Excel worksheet function)

<lang lisp>=LAMBDA(isUpper,

   LAMBDA(matrix,
       LET(
           nCols, COLUMNS(matrix),
           nRows, ROWS(matrix),
           ixs, SEQUENCE(nRows, nCols, 0, 1),
           x, MOD(ixs, nCols),
           y, QUOTIENT(ixs, nRows),
       
           IF(nCols=nRows,
               LET(
                   p, LAMBDA(x, y,
                       IF(isUpper, x > y, x < y)
                   ),
                   
                   IF(p(x, y), 
                       INDEX(matrix, 1 + y, 1 + x), 
                       0
                   )
               ),
               "Matrix not square"
           )
       )
   )

)</lang>

Output:

The formulae in cells B2 and B9 define and populate the matrices which fill the ranges B2:F6 and B9:F12

(The formula in B9 differs from that in B2 only in the first (Boolean) argument)

fx =matrixTriangle(FALSE)(B16#)
A B C D E F
1
2 Lower triangle: 0 0 0 0 0
3 2 0 0 0 0
4 3 1 0 0 0
5 12 14 17 0 0
6 7 1 3 9 0
7 Sum 69
8
9 Upper triangle: 0 3 7 8 10
10 0 0 16 14 4
11 0 0 0 18 11
12 0 0 0 0 20
13 0 0 0 0 0
14 Sum 111
15
16 Full matrix 1 3 7 8 10
17 2 4 16 14 4
18 3 1 9 18 11
19 12 14 17 18 20
20 7 1 3 9 5

F#

<lang fsharp> // Sum below leading diagnal. Nigel Galloway: July 21st., 2021 let _,n=[[ 1; 3; 7; 8;10];

        [ 2; 4;16;14; 4];
        [ 3; 1; 9;18;11];
        [12;14;17;18;20];
        [ 7; 1; 3; 9; 5]]|>List.fold(fun(n,g) i->let i,_=i|>List.splitAt n in (n+1,g+(i|>List.sum)))(0,0) in printfn "%d" n

</lang>

Output:
69

Factor

Works with: Factor version 0.99 2021-06-02

<lang factor>USING: kernel math math.matrices prettyprint sequences ;

sum-below-diagonal ( matrix -- sum )
   dup square-matrix? [ "Matrix must be square." throw ] unless
   0 swap [ head sum + ] each-index ;

{

   { 1 3 7 8 10 }
   { 2 4 16 14 4 }
   { 3 1 9 18 11 }
   { 12 14 17 18 20 }
   { 7 1 3 9 5 }

} sum-below-diagonal .</lang>

Output:
69

Go

<lang go>package main

import (

   "fmt"
   "log"

)

func main() {

   m := [][]int{
       {1, 3, 7, 8, 10},
       {2, 4, 16, 14, 4},
       {3, 1, 9, 18, 11},
       {12, 14, 17, 18, 20},
       {7, 1, 3, 9, 5},
   }
   if len(m) != len(m[0]) {
       log.Fatal("Matrix must be square.")
   }
   sum := 0
   for i := 1; i < len(m); i++ {
       for j := 0; j < i; j++ {
           sum = sum + m[i][j]
       }
   }
   fmt.Println("Sum of elements below main diagonal is", sum)

}</lang>

Output:
Sum of elements below main diagonal is 69

Haskell

Defining both upper and lower triangle of a square matrix:

<lang haskell>----------------- UPPER OR LOWER TRIANGLE ----------------

matrixTriangle :: Bool -> a -> Either String a matrixTriangle upper matrix

 | upper = go drop id
 | otherwise = go take pred
 where
   go f g
     | isSquare matrix =
       (Right . snd) $
         foldr
           (\xs (n, rows) -> (pred n, f n xs : rows))
           (g $ length matrix, [])
           matrix
     | otherwise = Left "Defined only for a square matrix."

isSquare :: a -> Bool isSquare rows = all ((n ==) . length) rows

 where
   n = length rows

TEST -------------------------

main :: IO () main =

 mapM_ putStrLn $
   zipWith
     ( flip ((<>) . (<> " triangle:\n\t"))
         . either id (show . sum . concat)
     )
     ( [matrixTriangle] <*> [False, True]
         <*> [ [ [1, 3, 7, 8, 10],
                 [2, 4, 16, 14, 4],
                 [3, 1, 9, 18, 11],
                 [12, 14, 17, 18, 20],
                 [7, 1, 3, 9, 5]
               ]
             ]
     )
     ["Lower", "Upper"]</lang>
Output:
Lower triangle:
    69
Upper triangle:
    111

J

<lang j>sum_below_diagonal =: [:+/@,[*>/~@i.@#</lang>

Output:
   mat
 1  3  7  8 10
 2  4 16 14  4
 3  1  9 18 11
12 14 17 18 20
 7  1  3  9  5
   sum_below_diagonal mat
69

JavaScript

Defining the lower triangle of a square matrix.

<lang javascript>(() => {

   "use strict";
   // -------- LOWER TRIANGLE OF A SQUARE MATRIX --------
   // lowerTriangle :: a -> Either String a
   const lowerTriangle = matrix =>
       // Either a message, if the matrix is not square,
       // or the lower triangle of the matrix.
       isSquare(matrix) ? (
           Right(
               matrix.reduce(
                   ([n, rows], xs) => [
                       1 + n,
                       rows.concat([xs.slice(0, n)])
                   ],
                   [0, []]
               )[1]
           )
       ) : Left("Not a square matrix");


   // isSquare :: a -> Bool
   const isSquare = rows => {
       // True if the length of every row in the matrix
       // matches the number of rows in the matrix.
       const n = rows.length;
       return rows.every(x => n === x.length);
   };
   // ---------------------- TEST -----------------------
   const main = () =>
       either(
           msg => `Lower triangle undefined :: ${msg}`
       )(
           rows => sum([].concat(...rows))
       )(
           lowerTriangle([
               [1, 3, 7, 8, 10],
               [2, 4, 16, 14, 4],
               [3, 1, 9, 18, 11],
               [12, 14, 17, 18, 20],
               [7, 1, 3, 9, 5]
           ])
       );
   // --------------------- GENERIC ---------------------
   // Left :: a -> Either a b
   const Left = x => ({
       type: "Either",
       Left: x
   });


   // Right :: b -> Either a b
   const Right = x => ({
       type: "Either",
       Right: x
   });


   // either :: (a -> c) -> (b -> c) -> Either a b -> c
   const either = fl =>
       // Application of the function fl to the
       // contents of any Left value in e, or
       // the application of fr to its Right value.
       fr => e => e.Left ? (
           fl(e.Left)
       ) : fr(e.Right);


   // sum :: [Num] -> Num
   const sum = xs =>
       // The numeric sum of all values in xs.
       xs.reduce((a, x) => a + x, 0);
   // MAIN ---
   return main();

})();</lang>

Output:
69

jq

Works with: jq

Works with gojq, the Go implementation of jq <lang jq> def add(s): reduce s as $x (null; . + $x);

  1. input: a square matrix

def sum_below_diagonal:

 add( range(0;length) as $i | .[$i][:$i][] ) ;

</lang> The task: <lang jq> [[1,3,7,8,10],

  [2,4,16,14,4],
  [3,1,9,18,11],
  [12,14,17,18,20],
  [7,1,3,9,5]]
 | sum_below_diagonal</lang> 
Output:
69


Julia

The tril function is part of Julia's built-in LinearAlgebra package. tril(A) includes the main diagonal and the components of the matrix A to the left and below the main diagonal. tril(A, -1) returns the lower triangular elements of A excluding the main diagonal. The excluded elements of the matrix are set to 0. <lang julia>using LinearAlgebra

A = [ 1 3 7 8 10;

     2  4 16 14  4;
     3  1  9 18 11;
    12 14 17 18 20;
     7  1  3  9  5 ]

@show tril(A)

@show tril(A, -1)

@show sum(tril(A, -1)) # 69

</lang>

Output:

tril(A) = [1 0 0 0 0; 2 4 0 0 0; 3 1 9 0 0; 12 14 17 18 0; 7 1 3 9 5] tril(A, -1) = [0 0 0 0 0; 2 0 0 0 0; 3 1 0 0 0; 12 14 17 0 0; 7 1 3 9 0] sum(tril(A, -1)) = 69

Mathematica/Wolfram Language

<lang Mathematica>m = {{1, 3, 7, 8, 10}, {2, 4, 16, 14, 4}, {3, 1, 9, 18, 11}, {12, 14, 17, 18, 20}, {7, 1, 3, 9, 5}}; Total[LowerTriangularize[m, -1], 2]</lang>

Output:
69

MiniZinc

<lang MiniZinc> % Sum below leading diagnal. Nigel Galloway: July 22nd., 2021 array [1..5,1..5] of int: N=[|1,3,7,8,10|2,4,16,14,4|3,1,9,18,11|12,14,17,18,20|7,1,3,9,5|]; int: res=sum(n,g in 1..5 where n>g)(N[n,g]); output([show(res)]) </lang>

Output:
69
----------

Nim

We use a generic definition for the square matrix type. The compiler insures that the matrix we provide is actually square.

<lang Nim>type SquareMatrix[T: SomeNumber; N: static Positive] = array[N, array[N, T]]

func sumBelowDiagonal[T, N](m: SquareMatrix[T, N]): T =

 for i in 1..<N:
   for j in 0..<i:
     result += m[i][j]

const M = [[ 1, 3, 7, 8, 10],

          [ 2,  4, 16, 14,  4],
          [ 3,  1,  9, 18, 11],
          [12, 14, 17, 18, 20],
          [ 7,  1,  3,  9,  5]]

echo sumBelowDiagonal(M)</lang>

Output:
69

Perl

<lang perl>#!/usr/bin/perl

use strict; use warnings; use List::Util qw( sum );

my $matrix =

 [[1,3,7,8,10],
 [2,4,16,14,4],
 [3,1,9,18,11],
 [12,14,17,18,20],
 [7,1,3,9,5]];

my $lowersum = sum map @{ $matrix->[$_] }[0 .. $_ - 1], 1 .. $#$matrix; print "lower sum = $lowersum\n";</lang>

Output:
lower sum = 69

Phix

constant M = {{ 1,  3,  7,  8, 10},
              { 2,  4, 16, 14,  4},
              { 3,  1,  9, 18, 11},
              {12, 14, 17, 18, 20},
              { 7,  1,  3,  9,  5}}
atom res = 0
integer height = length(M)
for row=1 to height do
    integer width = length(M[row])
    if width!=height then crash("not square") end if
    for col=1 to row-1 do
        res += M[row][col]
    end for
end for
?res

You could of course start row from 2 and get the same result, for row==1 the col loop iterates zero times.
Without the checks for square M expect (when not square) wrong/partial answers for height<=width+1, and (still human readable) runtime crashes for height>width+1.

Output:
69

PL/M

This can be compiled with the original 8080 PL/M compiler and run under CP/M or an emulator/clone. <lang pli>100H: /* SUM THE ELEMENTS BELOW THE MAIN DIAGONAL OF A MATRIX */

  /* CP/M BDOS SYSTEM CALL, IGNORE THE RETURN VALUE                         */
  BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5;     END;
  PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S );      END;
  PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH  */
     DECLARE N ADDRESS;
     DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
     V = N;
     W = LAST( N$STR );
     N$STR( W ) = '$';
     N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
     DO WHILE( ( V := V / 10 ) > 0 );
        N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
     END;
     CALL PR$STRING( .N$STR( W ) );
  END PR$NUMBER;
  /* RETURNS THE SUM OF THE ELEMENTS BELOW THE MAIN DIAGONAL OF MX          */
  /* MX WOULD BE DECLARED AS ( UB, UB )ADDRESS IF PL/M SUPPORTED        */
  /* 2-DIMENSIONAL ARRAYS, IT DOESN'T SO MX MUST ACTULLY BE DECLARED        */
  /* ( UB * UB )ADDRESS - EXCEPT THE BOUND MUST BE A CONSTANT, NOT AN   */
  /* EXPRESSION                                                             */
  /* NOTE ADDRESS MEANS UNSIGNED 16-BIT QUANTITY, WHICH CAN BE USED FOR */
  /* OTHER PURPOSES THAN JUST POINTERS                                      */
  LOWER$SUM: PROCEDURE( MX, UB )ADDRESS;
     DECLARE ( MX, UB ) ADDRESS;
     DECLARE ( SUM, R, C, STRIDE, R$PTR ) ADDRESS;
     DECLARE M$PTR ADDRESS, M$VALUE BASED M$PTR ADDRESS;
     SUM    = 0;
     STRIDE = UB + UB;
     R$PTR  = MX + STRIDE;      /* ADDRESS OF ROW 1 ( THE FIRST ROW IS 0 )  */
     DO R = 1 TO UB - 1;
        M$PTR = R$PTR;
        DO C = 0 TO R - 1;
           SUM = SUM + M$VALUE;
           M$PTR = M$PTR + 2;
        END;
        R$PTR = R$PTR + STRIDE; /* ADDRESS OF THE NEXT ROW                  */
     END;
     RETURN SUM;
  END LOWER$SUM ;
  /* TASK TEST CASE                                                         */
  DECLARE T ( 25 )ADDRESS
                  INITIAL(  1,  3,  7,  8, 10
                         ,  2,  4, 16, 14,  4
                         ,  3,  1,  9, 18, 11
                         , 12, 14, 17, 18, 20
                         ,  7,  1,  3,  9,  5
                         );
  CALL PR$NUMBER( LOWER$SUM( .T, 5 ) );

EOF</lang>

Output:
69


Python

<lang python>from numpy import array, tril, sum

A = [[1,3,7,8,10],

   [2,4,16,14,4],
   [3,1,9,18,11],
   [12,14,17,18,20],
   [7,1,3,9,5]]

print(sum(tril(A, -1))) # 69</lang>


Or, defining the lower triangle for ourselves:

<lang python>Lower triangle of a matrix

from itertools import chain, islice from functools import reduce


  1. lowerTriangle :: a -> None | a

def lowerTriangle(matrix):

   Either None, if the matrix is not square, or
      the rows of the matrix, each containing only
      those values that form part of the lower triangle.
   
   def go(n_rows, xs):
       n, rows = n_rows
       return 1 + n, rows + [list(islice(xs, n))]
   return reduce(
       go,
       matrix,
       (0, [])
   )[1] if isSquare(matrix) else None


  1. isSquare :: a -> Bool

def isSquare(matrix):

   True if all rows of the matrix share
      the length of the matrix itself.
   
   n = len(matrix)
   return all([n == len(x) for x in matrix])


  1. ------------------------- TEST -------------------------
  2. main :: IO ()

def main():

   Sum of integers in the lower triangle of a matrix.
   
   rows = lowerTriangle([
       [1, 3, 7, 8, 10],
       [2, 4, 16, 14, 4],
       [3, 1, 9, 18, 11],
       [12, 14, 17, 18, 20],
       [7, 1, 3, 9, 5]
   ])
   print(
       "Not a square matrix." if None is rows else (
           sum(chain(*rows))
       )
   )
  1. MAIN ---

if __name__ == '__main__':

   main()</lang>
Output:
69

R

R has lots of native matrix support, so this is trivial. <lang R>mat <- rbind(c(1,3,7,8,10),

            c(2,4,16,14,4),
            c(3,1,9,18,11),
            c(12,14,17,18,20),
            c(7,1,3,9,5))

print(sum(mat[lower.tri(mat)]))</lang>

Output:
[1] 69

Raku

<lang perl6>sub lower-triangle-sum (@matrix) { sum flat (1..@matrix).map( { @matrix[^$_]»[^($_-1)] } )»[*-1] }

say lower-triangle-sum [

   [  1,  3,  7,  8, 10 ],
   [  2,  4, 16, 14,  4 ],
   [  3,  1,  9, 18, 11 ],
   [ 12, 14, 17, 18, 20 ],
   [  7,  1,  3,  9,  5 ]

];</lang>

Output:
69

REXX

version 1

<lang rexx>/* REXX */ ml ='1 3 7 8 10 2 4 16 14 4 3 1 9 18 11 12 14 17 18 20 7 1 3 9 5' Do i=1 To 5

 Do j=1 To 5
   Parse Var ml m.i.j ml
   End
 End

l= Do i=1 To 5

 Do j=1 To 5
   l=l right(m.i.j,2)
   End
 Say l
 l=
 End

sum=0 Do i=2 To 5

 Do j=1 To i-1
   sum=sum+m.i.j
   End
 End

Say 'Sum below main diagonal:' sum</lang>

 
  1  3  7  8 10
  2  4 16 14  4
  3  1  9 18 11
 12 14 17 18 20
  7  1  3  9  5
Sum below main diagonal: 69 

version 2

This REXX version makes no assumption about the size of the matrix,   and it determines the maximum width of any
matrix element   (instead of assuming a width that might not properly show the true value of an element). <lang rexx>/*REXX pgm finds & shows the sum of elements below the main diagonal of a square matrix.*/ $= '1 3 7 8 10 2 4 16 14 4 3 1 9 18 11 12 14 17 18 20 7 1 3 9 5'; #= words($)

    do siz=1  while siz*siz<#;  end             /*determine the size of the matrix.    */

w= 0 /*W: the maximum width any any element*/

    do j=1  for #;         parse var $  @..j  $ /*obtain a number of the array (list). */
    w= max(w, length(@..j))                     /*examine each element for its width.  */
    end   /*j*/                                 /* [↑] this is aligning matrix elements*/

s= 0; z= 0 /*initialize the sum [S] to zero. */

    do      r=1  for siz;  _= left(, 12)      /*_:  contains a row of matrix elements*/
         do c=1  for siz;  z= z + 1;  @.z= @..z /*get a  number  of the    "      "    */
         _= _  right(@.z, w)                    /*build a row of elements for display. */
         if c<r  then s= s + @.z                /*add a  "lower element"  to the sum.  */
         end   /*r*/
    say _                                       /*display a row of the matrix to term. */
    end        /*c*/

say 'sum of elements below main diagonal is: ' s /*stick a fork in it, we're all done. */</lang>

output   when using the internal default input:
              1  3  7  8 10
              2  4 16 14  4
              3  1  9 18 11
             12 14 17 18 20
              7  1  3  9  5
sum of elements below main diagonal is:  69

Ring

<lang ring> see "working..." + nl see "Sum of elements below main diagonal of matrix:" + nl diag = [[1,3,7,8,10],

       [2,4,16,14,4],
       [3,1,9,18,11],
       [12,14,17,18,20],
       [7,1,3,9,5]]

lenDiag = len(diag) ind = lenDiag sumDiag = 0

for n=1 to lenDiag

   for m=1 to lenDiag-ind
       sumDiag += diag[n][m]
   next
   ind--

next

see "" + sumDiag + nl see "done..." + nl </lang>

Output:
working...
Sum of elements below main diagonal of matrix:
69
done...

Wren

<lang ecmascript>var m = [

   [ 1,  3,  7,  8, 10],
   [ 2,  4, 16, 14,  4],
   [ 3,  1,  9, 18, 11],
   [12, 14, 17, 18, 20],
   [ 7,  1,  3,  9,  5]

] if (m.count != m[0].count) Fiber.abort("Matrix must be square.") var sum = 0 for (i in 1...m.count) {

  for (j in 0...i) {
      sum = sum + m[i][j]
 }

} System.print("Sum of elements below main diagonal is %(sum).")</lang>

Output:
Sum of elements below main diagonal is 69.

XPL0

<lang XPL0>int Mat, X, Y, Sum; [Mat:= [[1,3,7,8,10],

       [2,4,16,14,4],
       [3,1,9,18,11],
       [12,14,17,18,20],
       [7,1,3,9,5]];

Sum:= 0; for Y:= 0 to 4 do

 for X:= 0 to 4 do
   if Y > X then
     Sum:= Sum + Mat(Y,X);

IntOut(0, Sum); ]</lang>

Output:
69