Sum the deltas of my matrix

17

2

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

Mr. Xcoder

Posted 2017-09-10T10:33:11.300

Reputation: 39 774

Answers

12

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(...)).

Jonathan Allan

Posted 2017-09-10T10:33:11.300

Reputation: 67 804

8

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.

Stewie Griffin

Posted 2017-09-10T10:33:11.300

Reputation: 43 471

8

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.

Giuseppe

Posted 2017-09-10T10:33:11.300

Reputation: 21 077

5

Jelly, 5 bytes

;ZIẎS

Try it online!

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

Erik the Outgolfer

Posted 2017-09-10T10:33:11.300

Reputation: 38 134

5

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

Arnauld

Posted 2017-09-10T10:33:11.300

Reputation: 111 334

5

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

Stewie Griffin

Posted 2017-09-10T10:33:11.300

Reputation: 43 471

4

05AB1E, 6 bytes

ø«€¥OO

Uses the 05AB1E encoding. Try it online!

Adnan

Posted 2017-09-10T10:33:11.300

Reputation: 41 965

4

J, 14 bytes

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

Try it online!

Explanation

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

miles

Posted 2017-09-10T10:33:11.300

Reputation: 15 654

3

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

Erik the Outgolfer

Posted 2017-09-10T10:33:11.300

Reputation: 38 134

Yep, 8 bytes, using . – Mr. Xcoder – 2017-09-10T11:34:23.037

8 bytes too, using your approach instead. – Mr. Xcoder – 2017-09-10T11:35:08.070

@Mr.Xcoder wow forgot about that – Erik the Outgolfer – 2017-09-10T11:35:09.567

3

APL, 18 15 bytes

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

Try it online!

Zacharý

Posted 2017-09-10T10:33:11.300

Reputation: 5 710

13 bytes - +/∘∊(2-⍨/⍉⍪⊢) – Uriel – 2018-01-10T21:22:00.563

@Uriel that works only for square matrices – ngn – 2018-02-05T23:58:28.263

3

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

Laikoni

Posted 2017-09-10T10:33:11.300

Reputation: 23 676

3

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!

Kroppeb

Posted 2017-09-10T10:33:11.300

Reputation: 1 558

2

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;

user70974

Posted 2017-09-10T10:33:11.300

Reputation:

.t can be C for -1. – Erik the Outgolfer – 2017-09-10T10:50:06.697

@EriktheOutgolfer Oh wow, thanks! – None – 2017-09-10T10:50:59.153

2

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

Shaggy

Posted 2017-09-10T10:33:11.300

Reputation: 24 623

2

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

sundar - Reinstate Monica

Posted 2017-09-10T10:33:11.300

Reputation: 5 296

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!

– Kroppeb – 2018-08-20T22:02:15.617

using ⟨≡{...}ᵐ\⟩+ instead of {...}R&\↰₁;R+ saves 2 bytes. Resulting in ⟨≡{⟨t-h⟩ᵐ+}ᵐ\⟩+ Try it online!

– Kroppeb – 2018-08-20T22:41:47.500

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!

– Kroppeb – 2018-08-20T22:55:00.627

@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.

– sundar - Reinstate Monica – 2018-08-28T14:21:26.657

1

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

dzaima

Posted 2017-09-10T10:33:11.300

Reputation: 19 048

1 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? – Mr. Xcoder – 2017-09-10T10:40:01.703

@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)

– dzaima – 2017-09-10T10:44:31.703

Oh, alright. It is perfectly valid then. – Mr. Xcoder – 2017-09-10T10:45:18.773

1

Mathematica, 45 bytes

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

Input

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

J42161217

Posted 2017-09-10T10:33:11.300

Reputation: 15 931

Would it be shorter to subtract the first from the last for each array in {#,Transpose@#} (like my Python answer)? – Jonathan Allan – 2017-09-10T11:21:42.260

Total[Differences/@{#,Thread@#},3]& – alephalpha – 2017-09-10T12:19:40.400

1

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

Luis Mendo

Posted 2017-09-10T10:33:11.300

Reputation: 87 464

4This answer needs more colons. There are 2few colons. – Esolanging Fruit – 2017-09-10T20:52:32.310

0

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

Zacharý

Posted 2017-09-10T10:33:11.300

Reputation: 5 710

0

APL (Dyalog Classic), 12 bytes

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

Try it online!

ngn

Posted 2017-09-10T10:33:11.300

Reputation: 11 449

0

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

mudkip201

Posted 2017-09-10T10:33:11.300

Reputation: 833