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│
└────────────────────────────────────────────────────────────────┘

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)

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


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!


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.


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

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

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}]


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.


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


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

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!


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.