17
\$\begingroup\$

Background

The deltas of an array of integers is the array formed by getting the differences of consecutive elements. For example, [1, 2, 4, 7, 3, 9, 6] has the following deltas: [1, 2, 3, -4, 6, -3].

We will now define the deltas of a matrix of integers as the deltas of each row and each column it contains.

As an example:

Row deltas:

1 2 3 4 │ => [1, 1, 1]
4 5 6 7 │ => [1, 1, 1]
7 1 8 2 │ => [-6, 7, -6]

Column deltas (the matrix' columns have been rotated into rows for simplicity):

1 4 7 │ => [3, 3] 
2 5 1 │ => [3, -4]
3 6 8 │ => [3, 2]
4 7 2 │ => [3, -5]

Which gives us the following list of matrix deltas:

[[1, 1, 1], [1, 1, 1], [-6, 7, -6], [3, 3], [3, -4], [3, 2], [3, -5]]

And as we don't want them to be nested, we flatten that list:

[1, 1, 1, 1, 1, 1, -6, 7, -6, 3, 3, 3, -4, 3, 2, 3, -5]

Task

Your task is to sum all the deltas of a matrix given as input. Note that the matrix will only consist of non-negative integers.

Rules

  • All standard rules apply.

  • You may assume the matrix contains at least two values on each row and column, so the minimum size will be 2x2.

  • You may take the matrix in any reasonable format, as long as you specify it.

  • You may not assume that the matrix is square.

  • If it might help you reduce your byte count, you may optionally take the number of rows and the number of columns as input as well (Looking at you C!).

  • This is code-golf, so the shortest code (in bytes), in each language wins!

Test Cases

Input  =>  Output

[[1, 2], [1, 2]]                                    => 2
[[8, 7, 1], [4, 1, 3], [5, 5, 5]]                   => -9
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]                   => 24
[[9, 9, 9, 9, 9], [9, 9, 9, 9, 9]]                  => 0
[[1, 3, 14], [56, 89, 20], [99, 99, 99]]            => 256
[[1, 2, 3, 4], [4, 5, 6, 7], [7, 1, 8, 2]]          => 9
[[13, 19, 478], [0, 12, 4], [45, 3, 6], [1, 2, 3]]  => -72
\$\endgroup\$

21 Answers 21

12
\$\begingroup\$

Python 2, 42 bytes

lambda m:sum(r[-1]-r[0]for r in m+zip(*m))

An unnamed function taking a list of lists, m, and returning the resulting number.

Try it online!

How?

The sum of the deltas of a list is the last element minus the first, everything else just cancels:
(r[n]-r[n-1])+(r[n-1]-r[n-2])+...+(r[2]-r[1]) = r[n]-r[1]

The zip(*m) uses unpacking (*) of m to pass the rows of m as separate arguments to zip (interleave) and hence transposes the matrix. In python 2 this yields a list (of tuples, but that's fine), so we can add (concatenate) it to (with) m, step through all our rows and columns, r, perform the above trick for each and just add up the results (sum(...)).

\$\endgroup\$
8
\$\begingroup\$

R, 34 bytes

function(m)sum(diff(m),diff(t(m)))

Try it online!

Anonymous function. Originally, I used apply(m,1,diff) to get the rowwise diffs (and 2 instead of 1 for columns) but looking at Stewie Griffin's answer I tried it with just diff and it worked.

\$\endgroup\$
8
\$\begingroup\$

Octave, 33 bytes

@(x)sum([diff(x)(:);diff(x')(:)])

Try it online!

Explanation:

This is an anonymous function taking x as input. It takes the difference between all columns, and concatenates it with the difference between the columns of the transposed of x. It then sums this vector along the second dimension.

\$\endgroup\$
5
\$\begingroup\$

Jelly, 5 bytes

;ZIẎS

Try it online!

There are a couple ASCII-only versions too: ;ZIFS ;ZISS

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 68 67 bytes

m=>m.map(r=>s+=[...l=r].pop()-r[0],s=0)|m[0].map(v=>s+=l.pop()-v)|s

Formatted and commented

m =>                              // given a matrix m
  m.map(r =>                      // for each row r of m
    s += [...l = r].pop() - r[0], //   add to s: last value of r - first value of r
    s = 0                         //   starting with s = 0
  ) |                             //
  m[0].map(v =>                   // for each value v in the first row of m:
    s += l.pop() - v              //   add to s: last value of last row of m - v
  ) |                             //
  s                               // return s

Because the minimum size of the input matrix is 2x2, m.map(...)|m[0].map(...) is guaranteed to be coerced to 0. That's why it's safe to return the final result with |s.

Test cases

let f =

m=>m.map(r=>s+=[...l=r].pop()-r[0],s=0)|m[0].map(v=>s+=l.pop()-v)|s

console.log(f( [[1, 2], [1, 2]]                                   )) // => 2
console.log(f( [[8, 7, 1], [4, 1, 3], [5, 5, 5]]                  )) // => -9
console.log(f( [[1, 2, 3], [4, 5, 6], [7, 8, 9]]                  )) // => 24
console.log(f( [[9, 9, 9, 9, 9], [9, 9, 9, 9, 9]]                 )) // => 0
console.log(f( [[1, 3, 14], [56, 89, 20], [99, 99, 99]]           )) // => 256
console.log(f( [[1, 2, 3, 4], [4, 5, 6, 7], [7, 1, 8, 2]]         )) // => 9
console.log(f( [[13, 19, 478], [0, 12, 4], [45, 3, 6], [1, 2, 3]] )) // => -72

\$\endgroup\$
5
\$\begingroup\$

MATL, 7 bytes

dG!dhss

Try it online!

Explanation:

Suppose the input is

[8 7 1; 4 1 3; 5 5 5]

d        % Difference between rows of input
         % Stack:
         % [-4 -6  2; 1  4  2]
 G       % Grab the input again. Stack:
         % [-4 -6  2; 1  4  2]
         % [8 7 1; 4 1 3; 5 5 5]]
  !      % Transpose the bottom element. Stack:
         % [-4 -6  2; 1  4  2]
         % [8 4 5; 7 1 5; 1 3 5]
   d     % Difference between rows. Stack:
         % [-4 -6  2; 1  4  2]
         % [-1 -3  0; -6  2  0]
    h    % Concatenate horizontally. Stack:
         % [-4 -6  2 -1 -3  0; 1  4  2 -6  2  0]
     ss  % Sum each column, then sum all column sums. Stack:
         % -9
\$\endgroup\$
4
\$\begingroup\$

05AB1E, 6 bytes

ø«€¥OO

Uses the 05AB1E encoding. Try it online!

\$\endgroup\$
4
\$\begingroup\$

J, 14 bytes

+/@,&({:-{.)|:

Try it online!

Explanation

+/@,&({:-{.)|:  Input: matrix M
            |:  Transpose
     (     )    Operate on M and M'
      {:          Tail
        -         Minus
         {.       Head
   ,&           Join
+/@             Reduce by addition
\$\endgroup\$
3
\$\begingroup\$

Husk, 7 bytes

ΣṁẊ-S+T

Try it online!

-1 thanks to Mr. Xcoder taking my focus away from the S and ¤ and towards the m (which should've been ).
-1 thanks to Zgarb abusing S.

Explanation:

ΣṁẊ-S+T 3-function composition
    S   (x -> y -> z) (f) -> (x -> y) (g) -> x (x) (implicit): f x g x
     +    f: [x] (x) -> [x] (y) -> [x]: concatenate two lists
      T   g: [[x]] (x) -> [[x]]: transpose x
 ṁ      (x -> [y]) (f) -> [x] (x) -> [y]: map f on x and concatenate
  Ẋ       f: (x -> y -> z) (f) -> [x] (x) -> [z]: map f on splat overlapping pairs of x
   -        f: TNum (x) -> TNum (y) -> TNum: y - x
Σ       [TNum] (x) -> TNum: sum x
\$\endgroup\$
  • \$\begingroup\$ Yep, 8 bytes, using . \$\endgroup\$ – Mr. Xcoder Sep 10 '17 at 11:34
  • \$\begingroup\$ 8 bytes too, using your approach instead. \$\endgroup\$ – Mr. Xcoder Sep 10 '17 at 11:35
  • \$\begingroup\$ @Mr.Xcoder wow forgot about that \$\endgroup\$ – Erik the Outgolfer Sep 10 '17 at 11:35
3
\$\begingroup\$

APL, 18 15 bytes

{-+/∊2-/¨⍵(⍉⍵)}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 13 bytes - +/∘∊(2-⍨/⍉⍪⊢) \$\endgroup\$ – Uriel Jan 10 '18 at 21:22
  • \$\begingroup\$ @Uriel that works only for square matrices \$\endgroup\$ – ngn Feb 5 '18 at 23:58
3
\$\begingroup\$

Haskell, 60 bytes

e=[]:e
z=zipWith
f s=sum$(z(-)=<<tail)=<<(s++foldr(z(:))e s)

Try it online! Uses the shorter transpose I found a while ago.

Explanation

e is an infinite list of empty lists and used for the transposing. z is a shorthand for the zipWith function, because it is used twice.

f s=                                        -- input s is a list of lists
                            foldr(z(:))e s  -- transpose s
                         s++                -- append the result to the original list s
                     =<<(                 ) -- map the following function over the list and concatenate the results
        (z(-)=<<tail)                       -- compute the delta of each list by element-wise subtracting its tail
    sum$                                    -- compute the sum of the resulting list
\$\endgroup\$
3
\$\begingroup\$

Brachylog, 13 bytes

orignally based of @sundar's design

⟨≡⟨t-h⟩ᵐ²\⟩c+ 

Explanation

⟨≡      \⟩          #   Take the original matrix and it's transpose 
      ᵐ             #       and execute the following on both
       ²            #           map for each row (this is now a double map "ᵐ²")
  ⟨t h⟩             #               take head and tail
   -                #               and subtract them from each other (sum of deltas in a row)
         c+         #       and add all the values 
                    #           (we have two arrays of arrays so we concat them and sum them)

the ⟨⟩ are messing up formatting, sorry

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Pyth, 7 bytes

ss.+M+C

Try it here.

My first ever answer in a golfing language! Thanks to @EriktheOutgolfer for -1 byte!

Explanation

ss.+M+C    ~ This is a full program with implicit input (used twice, in fact)

      C    ~ Matrix transpose. Push all the columns;
     +     ~ Concatenate with the rows;
  .+M      ~ For each list;
  .+       ~ Get the deltas;
 s         ~ Flatten the list of deltas;
s          ~ Get the sum;
           ~ Print Implicitly;
\$\endgroup\$
  • \$\begingroup\$ .t can be C for -1. \$\endgroup\$ – Erik the Outgolfer Sep 10 '17 at 10:50
  • \$\begingroup\$ @EriktheOutgolfer Oh wow, thanks! \$\endgroup\$ – user70974 Sep 10 '17 at 10:50
2
\$\begingroup\$

Brachylog, 22 16 bytes

⟨≡{s₂ᶠc+ᵐ-}ᵐ\⟩+ṅ

Try it online!

(-6 bytes inspired by @Kroppeb's suggestions.)

?⟨≡{s₂ᶠc+ᵐ-}ᵐ\⟩+ṅ.       Full code (? and . are implicit input and output)
?⟨≡{       }ᵐ\⟩          Apply this on both the input and its transpose:
    s₂ᶠ                  Get pairs of successive rows, [[row1, row2], [row2, row3], ...]
       c                 Flatten that: [row1, row2, row2, row3, row3, row4, ...]
        +ᵐ               Sum the elements within each row [sum1, sum2, sum2, sum3, ...]
          -              Get the difference between even-indexed elements (starting index 0)
                         and odd-indexed elements, i.e. sum1+sum2+sum3+... - (sum2+sum3+sum4+...)
                         This gets the negative of the usual difference i.e. a-b instead of b-a
                         for each pair of rows
               +         Add the results for the input and its transpose
                ṅ        Negate that to get the sign correct
                 .       That is the output
\$\endgroup\$
  • \$\begingroup\$ The sum of the deltas is equal to the last element-the first one ⟨t-h⟩ does the trick. Resulting in {⟨t-h⟩ᵐ+}R&\↰₁;R+ which is 5 bytes shorter. Try it online! \$\endgroup\$ – Kroppeb Aug 20 '18 at 22:02
  • \$\begingroup\$ using ⟨≡{...}ᵐ\⟩+ instead of {...}R&\↰₁;R+ saves 2 bytes. Resulting in ⟨≡{⟨t-h⟩ᵐ+}ᵐ\⟩+ Try it online! \$\endgroup\$ – Kroppeb Aug 20 '18 at 22:41
  • \$\begingroup\$ Changing the mapping of a map in a double map and concatenating and somming at the and removes an additional 2 bytes ⟨≡⟨t-h⟩ᵐ²\⟩c+. Try it online! \$\endgroup\$ – Kroppeb Aug 20 '18 at 22:55
  • \$\begingroup\$ @Kroppeb That's different enough and big enough of an improvement, that you should post it as a new answer yourself. Seeing your suggestions gave me an idea for a 16-byte solution using a different method ⟨≡{s₂ᶠc+ᵐ-}ᵐ\⟩+ṅ Try it online!, so I'll update this answer with that version instead. \$\endgroup\$ – sundar Aug 28 '18 at 14:21
2
\$\begingroup\$

Japt -x, 11 10 9 bytes

cUy)®än x

Try it


Explanation

c             :Concatenate
 U            :  Input array
  y           :  Transpose
   )          :End concatenation
    ®         :Map
     än       :  Deltas
        x     :  Reduce by addition
              :Implicitly reduce by addition and output
\$\endgroup\$
1
\$\begingroup\$

SOGL V0.12, 9 bytes

:⌡-≤H⌡-¹∑

Try it Here! ( added because this takes input on the stack)

Explanation:

:          duplicate ToS
 ⌡         for each do
  -          get deltas
   ≤       get the duplicate ontop
    H      rotate it anti-clockwise
     ⌡     for each do
      -      get deltas
       ¹   wrap all of that in an array
        ∑  sum
\$\endgroup\$
  • 1
    \$\begingroup\$ added because this takes input on the stack - I've been meaning to ask this for a long time: Is input pushed automatically to the stack? If it is not, and expects input to be already present in the stack, shouldn't you add in your byte count as well? Not sure how these situations are handled. Or is it like a function? \$\endgroup\$ – Mr. Xcoder Sep 10 '17 at 10:40
  • \$\begingroup\$ @Mr.Xcoder hmm.. I thought that was allowed by the default inputs, but I guess there's only this for functions.. Then again, I could call this an unnamed function used as this (in SOGL a "function"s definition is functionNameSingleChar\n) \$\endgroup\$ – dzaima Sep 10 '17 at 10:44
  • \$\begingroup\$ Oh, alright. It is perfectly valid then. \$\endgroup\$ – Mr. Xcoder Sep 10 '17 at 10:45
1
\$\begingroup\$

Mathematica, 45 bytes

Tr@Flatten[Differences/@#&/@{#,Transpose@#}]&

Input

[{{13, 19, 478}, {0, 12, 4}, {45, 3, 6}, {1, 2, 3}}]

\$\endgroup\$
  • \$\begingroup\$ Would it be shorter to subtract the first from the last for each array in {#,Transpose@#} (like my Python answer)? \$\endgroup\$ – Jonathan Allan Sep 10 '17 at 11:21
  • \$\begingroup\$ Total[Differences/@{#,Thread@#},3]& \$\endgroup\$ – alephalpha Sep 10 '17 at 12:19
1
\$\begingroup\$

CJam, 19 bytes

0q~_z+2few:::-:+:+-

Input is a list of lists of numbers. Try it online!

Explanation

0       e# Push 0
q~      e# Evaluated input. 
_       e# Duplicate
z       e# Zip (transpose)
+       e# Concatenate. This gives a lists of lists of numbers, where the
        e# inner lists are the original rows and the columns
2few    e# Replace each inner list of numbers by a list of overlapping
        e# slices of size 2. We not have three-level list nesting
:::-    e# Compute difference for each of those size-two slices. We now
        e# have the deltas for each row and column
:+      e# Concatenate all second-level lists (de-nest one level)
:+      e# Sum all values
-       e# Subtract from 0, to change sign. Implicitly display
\$\endgroup\$
  • 4
    \$\begingroup\$ This answer needs more colons. There are 2few colons. \$\endgroup\$ – Esolanging Fruit Sep 10 '17 at 20:52
0
\$\begingroup\$

MY, 9 bytes

ωΔω⍉Δ ḟΣ↵

Try it online!

Since I cannot ping Dennis in chat to pull MY (due to a suspension), this will currently not work. (Δ previously didn't vecify when subtracting) Thanks to whomever got Dennis to pull MY!

How?

  • ωΔ, increments of the first command line argument
  • ω⍉Δ, increments of the transpose of the first command line argument
  • , in a single list
  • , flatten
  • Σ, sum
  • , output
\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog Classic), 12 bytes

(+/⊢⌿,⊣/)⌽-⊖

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Pyt, 11 bytes

Đ⊤ʁ-⇹ʁ-áƑƩ~

Explanation:

          Implicit input (as a matrix)
Đ         Duplicate the matrix
⊤         Transpose the matrix
ʁ-        Get row deltas of transposed matrix
⇹         Swap top two elements on the stack
ʁ-        Get row deltas of original matrix
á         Push the stack into an array
Ƒ         Flatten the array
Ʃ         Sum the array
~         Flip the sign (because the deltas are negative, as subtraction was performed to obtain them)
          Implicit output
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.