Sum of elements below main diagonal of matrix: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Haskell}}: Added a type signature)
Line 133: Line 133:
| otherwise = Left "Not a square matrix."
| otherwise = Left "Not a square matrix."


isSquare :: [[a]] -> Bool
isSquare [] = True
isSquare [] = True
isSquare (row : rows) = all ((n ==) . length) rows
isSquare (row : rows) = all ((n ==) . length) rows

Revision as of 18:16, 20 July 2021

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

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 the lower triangle:

<lang haskell>---------------------- LOWER TRIANGLE --------------------

lowerTriangle :: a -> Either String a lowerTriangle matrix

 | isSquare matrix =
   (Right . snd) $
     foldr
       (\xs (n, rows) -> (pred n, [take n xs] <> rows))
       (pred $ length matrix, [])
       matrix
 | otherwise = Left "Not a square matrix."

isSquare :: a -> Bool isSquare [] = True isSquare (row : rows) = all ((n ==) . length) rows

 where
   n = length row

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

main :: IO () main =

 either
   putStrLn
   (print . sum . concat)
   (lowerTriangle testMatrix)

testMatrix :: Integer testMatrix =

 [ [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

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

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

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>

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). <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 #;  w= max(w,length(word($,j))) /*examine each element for its width.  */
    end   /*j*/

s= 0 /*initialize the sum; define the size.*/

    do      r=1  for siz;   _= left(, 12)     /*_:  contains a row of matrix elements*/
         do c=1  for siz;   parse var  $  x  $  /*get an element of the    "      "    */
         _= _  right(x, w)                      /*build a row of elements for display. */
         if c<r  then s=s + x                   /*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