Suma acumulativa particionada en 2D

16

Desafío

Dada una matriz M con r filas y c columnas, y dos listas booleanas V de longitud r y H de longitud c , calcule las sumas acumuladas verticales y horizontales divididas.

Reglas

  • r y c son mayores o iguales a uno

  • H y V comienzan con un valor verdadero

  • Los valores en M están dentro del dominio numérico razonable de su idioma.

  • El particionamiento y la suma comienzan en la esquina superior izquierda.

Ensayar

Dado M :

┌──────────────┐
│ 1  2  3  4  5│
│ 6  7  8  9 10│
│11 12 13 14 15│
│16 17 18 19 20│
└──────────────┘

H :1 0 1 0 0

V :1 1 0 1

Divida M en grupos de columnas, comenzando un nuevo grupo en cada valor verdadero de H

┌─────┬────────┐
│ 1  2│ 3  4  5│
│ 6  7│ 8  9 10│
│11 12│13 14 15│
│16 17│18 19 20│
└─────┴────────┘

Divida cada grupo de columnas en grupos de filas, comenzando un nuevo grupo en cada valor verdadero de V :

┌─────┬────────┐
│ 1  2│ 3  4  5│
├─────┼────────┤
│ 6  7│ 8  9 10│
│11 12│13 14 15│
├─────┼────────┤
│16 17│18 19 20│
└─────┴────────┘

Suma acumulativamente cada celda horizontalmente:

┌─────┬────────┐
│ 1  3│ 3  7 12│
├─────┼────────┤
│ 6 13│ 8 17 27│
│11 23│13 27 42│
├─────┼────────┤
│16 33│18 37 57│
└─────┴────────┘

Suma acumulativamente cada celda verticalmente:

┌─────┬────────┐
│ 1  3│ 3  7 12│
├─────┼────────┤
│ 6 13│ 8 17 27│
│17 36│21 44 69│
├─────┼────────┤
│16 33│18 37 57│
└─────┴────────┘

Resultado:

┌──────────────┐
│ 1  3  3  7 12│
│ 6 13  8 17 27│
│17 36 21 44 69│
│16 33 18 37 57│
└──────────────┘

Casos de prueba adicionales

M :

┌───────────┐
│15 11 11 17│
│13 20 18  8│
└───────────┘

H : 1 0 0 1V :1 0

Resultado:

┌───────────┐
│15 26 37 17│
│28 59 88 25│
└───────────┘

M :

┌─┐
│7│
└─┘

Resultado ( H y V deben ser 1):

┌─┐
│7│
└─┘

M :

┌──┐
│ 3│
│-1│
│ 4│
└──┘

V : 1 1 0( H debe ser 1)

Resultado:

┌──┐
│ 3│
│-1│
│ 3│
└──┘

M :

┌───────────────────────────────────────────────────────┐
│10    7.7 1.9 1.5 5.4  1.2 7.8 0.6 4.3 1.2  4.5 5.4 0.3│
│ 2.3  3.8 4.1 4.5 1    7.7 3   3.4 6.9 5.8  9.5 1.3 7.5│
│ 9.1  3.7 7.2 9.8 3.9 10   7.6 9.6 7.3 6.2  3.3 9.2 9.4│
│ 4.3  4.9 7.6 2   1.4  5.8 8.1 2.4 1.1 2.3  7.3 3.6 6  │
│ 9.3 10   5.8 9.6 5.7  8.1 2.1 3.9 4   1.3  6.3 3.1 9  │
│ 6.6  1.4 0.5 6.5 4.6  2.1 7.5 4.3 9   7.2  2.8 3.6 4.6│
│ 1.7  9.9 2.4 4.5 1.3  2.6 6.4 7.8 6.2 3.2 10   5.2 8.9│
│ 9.9  5.3 4.5 6.3 1.4  3.1 2.3 7.9 7.8 7.9  9.6 4   5.8│
└───────────────────────────────────────────────────────┘

H :1 0 0 1 0 1 1 1 0 1 1 1 0

V :1 0 0 0 0 1 0 0

Resultado:

┌────────────────────────────────────────────────────────────────┐
│10   17.7 19.6  1.5  6.9  1.2  7.8  0.6  4.9  1.2  4.5  5.4  5.7│
│12.3 23.8 29.8  6   12.4  8.9 10.8  4   15.2  7   14    6.7 14.5│
│21.4 36.6 49.8 15.8 26.1 18.9 18.4 13.6 32.1 13.2 17.3 15.9 33.1│
│25.7 45.8 66.6 17.8 29.5 24.7 26.5 16   35.6 15.5 24.6 19.5 42.7│
│35   65.1 91.7 27.4 44.8 32.8 28.6 19.9 43.5 16.8 30.9 22.6 54.8│
│ 6.6  8    8.5  6.5 11.1  2.1  7.5  4.3 13.3  7.2  2.8  3.6  8.2│
│ 8.3 19.6 22.5 11   16.9  4.7 13.9 12.1 27.3 10.4 12.8  8.8 22.3│
│18.2 34.8 42.2 17.3 24.6  7.8 16.2 20   43   18.3 22.4 12.8 32.1│
└────────────────────────────────────────────────────────────────┘
Adán
fuente

Respuestas:

9

Jalea , 10 bytes

Zœṗ@+\€Ẏð/

Pruébalo en línea! y El último caso de prueba (con un Gal final para facilitar la lectura).

La entrada se toma como una lista [M, H, V].

Explicación

Zœṗ@+\€Ẏð/  Input: [M, H, V]
        ð/  Insert the previous (f) as a dyadic link
            Forms f( f(M, H) , V)
            For f(x, y):
Z             Transpose x
 œṗ@          Partition the rows of x^T at each true in y
    +\€       Compute the cumulative sums in each partition
       Ẏ      Tighten (Joins all the lists at the next depth)
millas
fuente
Puede usar un pie de página como este para no tener que alterar su código real.
Erik the Outgolfer
7

APL (Dyalog) , 13 bytes

Toma ist de VHM como argumento.

{⍉⊃,/+\¨⍺⊂⍵}/

Pruébalo en línea!

{... }/ inserte (reduzca) la siguiente función anónima, donde el término de la izquierda está representado por ⍺ y el término de la derecha está representado por ⍵. Debido a que las funciones APL son asociativas correctas, esto es, por lo tanto, V f ( H f M ).

⍺⊂⍵ partición ⍵ según ⍺

+\¨ suma acumulativa de cada parte

,/ reducir por concatenación (esto incluye el resultado para reducir el rango)

 revelar

 transponer

Adán
fuente
6

Python 2 + numpy, 143 138 117 115 110 108 bytes

-21 bytes gracias a Adám !

lambda M,*L:reduce(lambda m,l:vstack(map(lambda p:cumsum(p,0),split(m,*where(l)))).T,L,M)
from numpy import*

Pruébalo en línea!

notjagan
fuente
1
pedir partición, división y cumsum una vez, transponer, repetir.
Adám
@ Adám Gracias, no pensé en eso por alguna razón.
notjagan
Me gustó la búsqueda de la lista de dos funciones de todos modos :)
Jonathan Allan
2
Haga el encabezado "Python 3 + numpy"
Leaky Nun
5

Jalea ,  15  14 bytes

œṗ+\€Ẏ
ḢçЀZð⁺

Un enlace diádico que toma H,Va la izquierda y Ma la derecha y devuelve la matriz resultante.

Pruébalo en línea!

Alternativamente como una sola línea también para 14: Ḣœṗ+\€Ẏ$¥Ð€Zð⁺

¿Cómo?

œṗ+\€Ẏ - Link 1: partition and cumSum: list of partition bools, list of values
œṗ     - partition (the values) at truthy indexes (of the bools)
    €  - for €ach part:
  +\   -   cumulative reduce by addition
     Ẏ - tighten (flattens back into a list)

ḢçЀZð⁺ - Main link: list of lists, [H,V]; list of lists, M
      ⁺ - perform this twice:
     ð  - [it's a dyadic chain for the second pass, first pass is dyadic implicitly]
Ḣ       -   head, pop it & modify (so H the first time, V the second)
  Ѐ    -   map across right: (M the first time, the intermediate result the second)
 ç      -     the last link (1) as a dyad
    Z   -   transpose the result (do the rows first time, and the columns the second)

Anterior:

œṗ@+\€Ẏ
ç€Zç€⁵Z

Un programa completo que imprime una representación del resultado.

Jonathan Allan
fuente
¡Whoa -50% de la respuesta anterior de Jelly!
Adám
Whoa que? Guau. Realmente necesito estudiar cómo hiciste esto ... ¡Increíble en comparación con el mío!
HyperNeutrino
Oh, esto está haciendo las dos direcciones por separado, ¿verdad? Inteligente.
HyperNeutrino
Creo que está haciendo más o menos lo mismo ...
Jonathan Allan
Buen método Significa que puedo vencer esto con APL. Tengo 14 bytes.
Adám
4

MATL , 19 bytes

,!ix"0GYs@12XQ!g]v!

Las entradas son M(matriz), H(vector de columna), V(vector de columna). El separador de fila es ;.

Pruébalo en línea! O verifique todos los casos de prueba: 1 , 2 , 3 , 4 , 5 .

Explicación

Esto hace la suma acumulativa horizontalmente, luego verticalmente.

,          % Do the following twice
  !        %   First time this inputs M implicitly. Transpose. Second time
           %   it transposes the result of the horizontal cumulative sum
  ix       %   Input H (first time) or V (second time). Delete it; but gets
           %   copied into clipboard G
  "        %   For each column of the matrix
    0G     %     Push most recent input: H (first time) or V (second)
    Ys     %     Cumulative sum. This produces a vector of integer values
           %     such that all columns (first time) or rows (second) of M 
           %     with the same value in this vector should be cumulatively
           %     summed
    @      %     Push current column of M transposed (first time) or M after
           %     horizontal cumulative sum (second time)
    12XQ   %     Cumulative sum. Gives a cell array of row vectors
    !g     %     Join those vectors into one row vector
  ]        %   End
  v        %   Concatenate the row vectors vertically into a matrix
  !        %   Transpose. This corrects for the fact that each column vector
           %   of the matrix was cumulatively summed into a row vector
           % Implicit end. Implicit display
Luis Mendo
fuente
1
Más impresionante. Supongo que Matlab fue hecho para cosas como esta.
Adám
@ Adám Estoy seguro de que la longitud de APL no será muy diferente :-)
Luis Mendo
Mi implementación de referencia utilizada para generar los casos de prueba es de 26 bytes.
Adám
@ Adám Darn! APL venciendo a Jelly? ¡Esto es inaceptable! (debe golf mi solución ... jajaja) xD
HyperNeutrino
@HyperNeutrino Bueno, Jelly no tiene tanto rango como profundidad como APL y J tienen.
Adám
3

J , 20 bytes

;@(<@(+/\);.1|:)&.>/

Pruébalo en línea!

La entrada se toma como una matriz de cuadros que contienen [V, H, M].

Explicación

;@(<@(+/\);.1|:)&.>/  Input: [V H M]
  (     g      )   /  Insert g and reduce (right-to-left)
                      Forms V g H g M = V g (H g M)
                & >     Unbox each
             |:         Transpose the right arg
          ;.1           Partition
      +/\               Reduce each prefix using addition (cumulative sum)
   <@                   Box each partition
;@                      Raze (Concatenate the contents in each box)
                &.>     Box the result
millas
fuente
2

Mathematica, 212 bytes

(T=Transpose;A=AppendTo;J=Flatten;f[s_]:=Block[{},t=2;r=1;w={};While[t<=Length@s,If[s[[t]]==0,r++,w~A~r;r=1];t++];w~A~r];K[x_,y_]:=Accumulate/@#&/@(FoldPairList[TakeDrop,#,f@y]&/@x);d=J/@K[#,#2];T[J/@K[T@d,#3]])&


entrada
[M, H, V]

[{{15, 11, 11, 17}, {13, 20, 18, 8}}, {1, 0, 0, 1}, {1, 0}]

J42161217
fuente
2

C # (.NET Core) , 164 bytes

(M,H,V)=>{int a=M.Length,b=M[0].Length,i,j;for(i=0;i<a;i++)for(j=0;j<b;j++)if(!H[j])M[i][j]+=M[i][j-1];for(i=0;i<a;i++)for(j=0;j<b;j++)if(!V[i])M[i][j]+=M[i-1][j];}

Pruébalo en línea!

Básicamente, hace exactamente lo especificado en el OP. Primero itera para sumar horizontalmente y luego itera nuevamente para sumar verticalmente.

Charlie
fuente
2

Haskell , 129 bytes 119 bytes

s m v=tail$scanl(\a(x,s)->if s then x else zipWith(+)a x)[](zip m v)
t=foldr(zipWith(:))$repeat[]
f m h v=t$s(t$s m v)h

Pruébalo en línea!

Guardado 10 bytes gracias a @ceasedtoturncounterclockwis

t(para transponer) cambia filas y columnas. Una explicación rápida:

foldr(zipWith(:))(repeat[])(r1,...,rn) =
zipWith(:) r1 (zipWith(:) r2 (... zipWith(:) rn (repeat [])))

Lea de derecha a izquierda: exploramos las filas de abajo hacia arriba y empujamos cada valor en su columna de destino.

s es básicamente una suma continua de vectores, pero se restablece cuando surge un valor Verdadero en v

fsuma las filas con el ssiguiente vy haz lo mismo con las siguientes columnash

jferard
fuente
t=foldr(zipWith(:))(repeat[]). No solo más corto, también mucho menos ineficiente.
dejó de girar en sentido contrario a las agujas del reloj el
@ceasedtoturncounterclockwis Gracias por la sugerencia.
jferard
1

JavaScript (ES6), 88 bytes

(a,h,v)=>a.map(b=>b.map((e,i)=>t=h[i]?e:t+e)).map((b,j)=>t=v[j]?b:t.map((e,i)=>e+b[i]))
Neil
fuente
0

Jalea , 31 bytes

+\€€
œṗḊZ€⁵œṗ$€Ḋ€Ç€ÇZ€€Z€;/€€;/

Pruébalo en línea!

Gah, esto es demasiado tiempo para Jelly xD

Por cierto, 11/31 bytes en este programa consta de caracteres en euros. ¡Eso es más de un tercio del programa!

Hiperneutrino
fuente
Demasiados euros.
Adám
@ Adám Mis pensamientos exactamente: P Trabajar con matrices doblemente particionadas no es tan divertido como pensé que sería, porque estoy haciendo un mapeo de segundo nivel a tercer nivel xD
HyperNeutrino
¿Por qué malgastas tu dinero de esta manera? € - €
V. Courtois