Soma cumulativa particionada em 2D

16

Desafio

Dada uma matriz H com r linhas e c colunas e duas listas booleana V de comprimento R e H de comprimento c , calcular os montantes verticais e horizontais cumulativos particionadas.

Regras

  • r e c são maiores ou iguais a um

  • H e V começam com um valor verdadeiro

  • Os valores em M estão dentro do domínio numérico razoável do seu idioma.

  • O particionamento e a soma começam no canto superior esquerdo.

Percorra

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 em grupos de colunas, iniciando um novo grupo com todo o valor verdadeiro 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 colunas em grupos de linhas, iniciando um novo grupo com todo o valor verdadeiro de V :

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

Soma cumulativamente cada célula horizontalmente:

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

Soma cumulativamente cada célula 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 teste adicionais

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 e V devem ser 1):

┌─┐
│7│
└─┘

M :

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

V : 1 1 0( H deve 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ão
fonte

Respostas:

9

Gelatina , 10 bytes

Zœṗ@+\€Ẏð/

Experimente online! e O último caso de teste (com um Gno final para facilitar a leitura).

A entrada é tomada como uma lista [M, H, V].

Explicação

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)
milhas
fonte
Você pode usar um rodapé como este para não precisar alterar seu código real.
Erik the Outgolfer
7

APL (Dyalog) , 13 bytes

Considera o VHM como argumento.

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

Experimente online!

{}/ Insira (reduza) a seguinte função anônima, onde o termo à esquerda é representado por ⍺ e o termo à direita é representado por ⍵. Devido ao fato das funções APL serem associativas, este é, portanto, V f ( H f M ).

⍺⊂⍵ partição ⍵ de acordo com ⍺

+\¨ soma acumulada de cada parte

,/ reduzir por concatenação (isso inclui o resultado para reduzir a classificação)

 divulgar

 transpor

Adão
fonte
6

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

-21 bytes graças 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*

Experimente online!

notjagan
fonte
1
peça partição, divida e cumsum uma vez, transponha e repita.
Adám
@ Adám Obrigado, eu não pensei nisso por algum motivo.
notjagan
Eu gostei da pesquisa lista de duas funções de qualquer maneira :)
Jonathan Allan
2
Por favor, crie o cabeçalho "Python 3 + numpy" #
Leaky Nun
5

Geléia ,  15  14 bytes

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

Um link diádico tomando H,Và esquerda e Mà direita e retornando a matriz resultante.

Experimente online!

Alternativamente, como uma única linha também para 14: Ḣœṗ+\€Ẏ$¥Ð€Zð⁺

Quão?

œṗ+\€Ẏ - 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

Um programa completo imprimindo uma representação do resultado.

Jonathan Allan
fonte
Whoa -50% da resposta anterior Jelly!
Adám
Whoa o que? Uau. Eu realmente preciso estudar como você fez isso ... Incrível comparado ao meu!
HyperNeutrino
Oh, isso está fazendo as duas direções separadamente, certo? Inteligente.
HyperNeutrino
Eu acho que ele está fazendo mais ou menos a mesma coisa ...
Jonathan Allan
Bom método Significa que eu posso superar isso com APL. Eu tenho 14 bytes.
Adám
4

MATL , 19 bytes

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

As entradas são M(matriz), H(vetor da coluna),V (vetor da coluna). O separador de linhas é ;.

Experimente online! Ou verifique todos os casos de teste: 1 , 2 , 3 , 4 , 5 .

Explicação

Isso faz a soma acumulada horizontalmente e depois 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
fonte
1
Mais impressionante. Eu acho que o Matlab foi feito para coisas assim.
Adám
@ Adám Tenho certeza comprimento da APL não será muito diferente :-)
Luis Mendo
Minha implementação de referência usada para gerar os casos de teste é de 26 bytes.
Adám
@ Adám Darn! APL batendo Jelly? Isso é inaceitável! (obrigação de golfe minha solução ... lol) xD
HyperNeutrino
@HyperNeutrino Bem, Jelly não tem classificação e profundidade, como APL e J têm.
Adám
3

J , 20 bytes

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

Experimente online!

A entrada é tomada como uma matriz de caixas contendo [V, H, M] .

Explicação

;@(<@(+/\);.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
milhas
fonte
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
fonte
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];}

Experimente online!

Basicamente, ele faz exatamente como especificado no OP. Primeiro itera para somar horizontalmente e depois itera novamente para somar verticalmente.

Charlie
fonte
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

Experimente online!

Guardado 10 bytes graças a @ceasedtoturncounterclockwis

t(para transposição) alterna linhas e colunas. Uma explicação rápida:

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

Leia da direita para a esquerda: navegamos nas linhas de baixo para cima e pressionamos cada valor em sua coluna de destino.

s é basicamente uma soma contínua de vetores, mas redefine quando um valor True surge em v

fsoma as linhas com o sseguinte ve faça o mesmo com as colunas a seguirh

jferard
fonte
t=foldr(zipWith(:))(repeat[]). Não apenas mais curto, também muito menos ineficiente.
deixou de girar no sentido contrário ao relógio
@ceasedtoturncounterclockwis Obrigado pela dica.
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
fonte
0

Gelatina , 31 bytes

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

Experimente online!

Gah, isso é muito longo para Jelly xD

Entre, 11/31 bytes neste programa consiste em caracteres em euro. Isso representa mais de um terço do programa!

HyperNeutrino
fonte
Muitos euros.
Adám
@ Adám Meus pensamentos exatamente: P Trabalho com matrizes duplamente divididos e não é tão divertido como eu pensei que seria, porque eu estou fazendo de segundo nível para de terceiro nível xD mapeamento
HyperNeutrino
Por que você está desperdiçando seu dinheiro assim? - €
V. Courtois