Stagger, stack, sum

15

Inspired by this Stack Overflow question.

The challenge

Input

An array of square matrices containing non-negative integers.

Output

A square matrix built from the input matrices as follows.

Let \$N \times N\$ be the size of each input matrix, and \$P\$ the number of input matrices.

For clarity, consider the following example input matrices (\$N=2\$, \$P=3\$):

 3   5
 4  10

 6   8
12  11

 2   0
 9   1
  1. Start with the first input matrix.
  2. Shift the second input matrix N−1 steps down and N−1 steps right, so that its upper-left entry coincides with the lower-right entry of the previous one.
  3. Imagine the second, shifted matrix as if it were stacked on top of the first. Sum the two values at the coincident entry. Write the other values, and fill the remaining entries with 0 to get a \$(2N-1)\times(2N-1)\$ matrix. With the example input, the result so far is

     3   5   0
     4  16   8
     0  12  11
    
  4. For each remaining input matrix, stagger it so that its upper-left coincides with the lower-right of the accumulated result matrix so far. In the example, including the third input matrix gives

     3   5   0   0
     4  16   8   0
     0  12  13   0
     0   0   9   1
    
  5. The ouput is the \$((N−1)P+1)\times((N−1)P+1)\$ matrix obtained after including the last input matrix.

Additional rules and clarifications

Test cases:

In each case, input matrices are shown first, then the output.

  1. \$N=2\$, \$P=3\$:

     3   5
     4  10
    
     6   8
    12  11
    
     2   0
     9   1
    
     3   5   0   0
     4  16   8   0
     0  12  13   0
     0   0   9   1
    
  2. \$N=2\$, \$P=1\$:

     3   5
     4  10
    
     3   5
     4  10
    
  3. \$N=1\$, \$P=4\$:

     4
    
     7
    
    23
    
     5
    
    39
    
  4. \$N=3\$, \$P=2\$:

    11  11   8
     6   8  12
    11   0   4
    
     4   1  13
     9  19  11
    13   4   2
    
    11  11   8   0   0
     6   8  12   0   0
    11   0   8   1  13
     0   0   9  19  11
     0   0  13   4   2
    
  5. \$N=2\$, \$P=4\$:

    14  13
    10   0
    
    13  20
    21   3
    
     9  22
     0   8
    
    17   3
    19  16
    
    14  13   0   0   0
    10  13  20   0   0
     0  21  12  22   0
     0   0   0  25   3
     0   0   0  19  16
    

Luis Mendo

Posted 2018-10-05T18:57:30.697

Reputation: 87 464

How long is your MATL solution for this? – Giuseppe – 2018-10-05T19:25:35.883

@Giuseppe I haven’t tried it in MATL. For the test cases I used the MATLAB code from my answer in the linked question – Luis Mendo – 2018-10-05T20:26:26.560

Answers

4

Jelly, 15 12 bytes

⁹ṖŻ€ƒZƲ⁺+µ@/

Try it online!

How it works

⁹ṖŻ€ƒZƲ⁺+µ@/  Main link. Argument: A (array of matrices)

         µ    Begin a monadic chain.
          @/  Reduce A by the previous chain, with swapped arguments.
                Dyadic chain. Arguments: M, N (matrices)
      Ʋ           Combine the links to the left into a monadic chain with arg. M.
⁹                 Set the return value to N.
 Ṗ                Pop; remove its last row.
     Z            Zip; yield M transposed.
    ƒ             Fold popped N, using the link to the left as folding function and
                  transposed M as initial value.
  Ż€                Prepend a zero to each row of the left argument.
                    The right argument is ignored.
       ⁺        Duplicate the chain created by Ʋ.
        +       Add M to the result.

Dennis

Posted 2018-10-05T18:57:30.697

Reputation: 196 637

6

R, 88 81 bytes

function(A,N,P,o=0*diag(P*(N-1)+1)){for(i in 1:P)o[x,x]=o[x<-1:N+i-1,x]+A[[i]];o}

Try it online!

Takes a list of matrices, A, N, and P.

Builds the requisite matrix of zeros o and adds elementwise the contents of A to the appropriate submatrices in o.

Giuseppe

Posted 2018-10-05T18:57:30.697

Reputation: 21 077

4

JavaScript (ES6), 102 bytes

Takes input as (n,p,a).

(n,p,a)=>[...Array(--n*p+1)].map((_,y,r)=>r.map((_,x)=>a.map((a,i)=>s+=(a[y-i*n]||0)[x-i*n]|0,s=0)|s))

Try it online!

How?

Redimensioning matrices filled with a default constant (\$0\$ in that case) is neither very easy nor very short in JS, so we just build a square matrix with the correct width \$w\$ right away:

$$w=(n-1)\times p+1$$

For each cell at \$(x,y)\$, we compute:

$$s_{x,y}=\sum_{i=0}^{p-1}{a_i(x-i\times (n-1),y-i\times (n-1))}$$

where undefined cells are replaced with zeros.

Arnauld

Posted 2018-10-05T18:57:30.697

Reputation: 111 334

3

Python 2, 124 bytes

def f(m,N,P):w=~-N*P+1;a=[w*[0]for _ in' '*w];g=0;exec"x=g/N/N*~-N;a[x+g/N%N][x+g%N]+=m[x][g/N%N][g%N];g+=1;"*P*N*N;return a

Try it online!

ovs

Posted 2018-10-05T18:57:30.697

Reputation: 21 408

3

Jelly, 12 bytes

Z€Ż€’}¡"Jµ⁺S

Try it online!

Z€Ż€’}¡"Jµ⁺S
         µ    Everything before this as a monad.
          ⁺   Do it twice
Z€            Zip €ach of the matrices
        J     1..P
       "      Pair the matrices with their corresponding integer in [1..P] then apply the 
              following dyad:
  Ż€            Prepend 0 to each of the rows
      ¡         Repeat this:
    ’}          (right argument - 1) number of times
              Doing everything before µ twice adds the appropriate number of rows and
              columns to each matrix. Finally:
           S  Sum the matrices.

12 bytes

J’0ẋ;Ɱ"Z€µ⁺S

If extra zeroes were allowed ZŻ€‘ɼ¡)⁺S is a cool 9 byte solution. TIO.

dylnan

Posted 2018-10-05T18:57:30.697

Reputation: 4 993

2

Jelly, 20 bytes

µ;€0Zð⁺0ṁ+ṚU$}ṚU+⁸µ/

Try it online!

Bah, Jelly has an attitude today...

Erik the Outgolfer

Posted 2018-10-05T18:57:30.697

Reputation: 38 134

2

Pip, 37 bytes

{i:0{Y#i-1aM:0RLyAL_i+:yZG#@aALa}Mai}

A function that takes a list of lists of lists. Try it online!

DLosc

Posted 2018-10-05T18:57:30.697

Reputation: 21 213

2

Python 2, 124 bytes

def f(A,N,P):M=N-1;R=G(M*P+1);return[[sum(A[k][i-k*M][j-k*M]for k in G(P)if j<N+k*M>i>=k*M<=j)for j in R]for i in R]
G=range

Try it online!

Chas Brown

Posted 2018-10-05T18:57:30.697

Reputation: 8 959

1

Charcoal, 52 bytes

≦⊖θE⊕×θηE⊕×θηΣEEη×θξ∧¬∨∨‹ιν›ι⁺θν∨‹λν›λ⁺θν§§§ζξ⁻ιν⁻λν

Try it online! Link is to verbose version of code and includes two bytes for somewhat usable formatting. I started off with a version that padded all the arrays and then summed them but I was able to golf this version to be shorter instead. Explanation:

≦⊖θ

Decrement the input value \$N\$.

E⊕×θηE⊕×θη

Compute the size of the result \$(N-1)P+1\$ and map over the implicit range twice thus producing a result matrix which is implcitly printed.

ΣEEη×θξ

Map over the implicit range over the input value \$P\$ and multiply each element by \$N-1\$. Then, map over the resulting range and sum the final result.

∧¬∨∨‹ιν›ι⁺θν∨‹λν›λ⁺θν

Check that neither of the indices are out of range.

§§§ζξ⁻ιν⁻λν

Offset into the original input to fetch the desired value.

Neil

Posted 2018-10-05T18:57:30.697

Reputation: 95 035