Calcular a soma acumulada limitada de um vetor

19

A soma acumulada de um vetor é calculada simplesmente com a soma de todos os elementos anteriores. Por exemplo:

vec =     [1  1  1 -1 -1 -1 -1 -1  1  1  1  1 -1]
cum_vec = [1  2  3  2  1  0 -1 -2 -1  0  1  2  1]

Agora, imponha um limite superior e um inferior, o que significa que você para de aumentar a soma acumulada se estiver no limite superior e para de diminuir a soma acumulada se estiver no limite inferior. Um exemplo simples:

upper_lim = 2
lower_lim = -1
vec =     [1  1  1 -1 -1 -1 -1 -1  1  1  1  1 -1]
cum_vec = [1  2  2  1  0 -1 -1 -1  0  1  2  2  1]

O vetor de entrada consiste em números inteiros, não necessariamente apenas 1e -1, positivos e negativos. Suponha isso upper_lim >= lower_lim. Se o primeiro elemento do vetor estiver fora do limite, pule diretamente para o limite (veja o último exemplo).

Escreva uma função que use um vetor de números inteiros como entrada e dois números inteiros que representam os limites superior e inferior. Saída do vetor cumulativo delimitado, conforme definido acima. A entrada pode ser como argumentos de função ou de STDIN.

Aplicam-se as regras de código padrão do golfe.

Exemplos:

upper_lim = 6
lower_lim = -2
vec =     [1  4  3 -10  3  2  2  5 -4]
cum_vec = [1  5  6  -2  1  3  5  6  2]

upper_lim = 100
lower_lim = -100
vec =     [1  1  1  1  1  1]
cum_vec = [1  2  3  4  5  6]

upper_lim = 5
lower_lim = 0
vec =     [10 -4 -3  2]
cum_vec = [5   1  0  2]

upper_lim = 0
lower_lim = 0
vec =     [3  5 -2  1]
cum_vec = [0  0  0  0]

upper_lim = 10
lower_lim = 5
vec =     [1  4  6]
cum_vec = [5  9 10]
           |
           Note, jumped to 5, because 5 is the lower bound.
Stewie Griffin
fonte

Respostas:

5

Pitão, 14 bytes

t.u@S+Q+NY1vwZ

Experimente on-line: Demonstration or Test Suite

Explicação

t.u@S+Q+NY1vwZ  implicit: Q = first input list [upper_lim, lower_lim]
 .u        vwZ  for each number Y in the next input list, update N = 0 with:
       +NY         N + Y
     +Q            append this to Q
    S              sort this list
   @      1        take the middle element
                .u returns a list with all intermediate values of N
t                  remove the first value, print the rest
Jakube
fonte
5

CJam, 16 15 bytes

l~f{\T++$1=:T}`

Experimente online

Isso leva a lista como primeiro argumento e o par de limite superior / inferior como uma segunda lista de 2 elementos. Exemplo de entrada:

[1 4 3 -10 3 2 2 5 -4] [6 -2]

A versão mais recente economiza 1 byte, classificando os 3 valores e assumindo o valor do meio, em vez de usar uma operação max e min. Isso também foi usado na solução de Jakube, assim como sugerido por Martin.

Explicação:

l~    Get and parse input. This leaves the value and bounds lists on the stack.
f{    Apply block with value (the bounds list).
  \     Swap new value to top.
  T     Get previous value from variable T (which is default initialized to 0).
  +     Add new value and previous value.
  +     Append new value to bounds list, producing a 3 value list.
  $     Sort it...
  1=    And take the middle value.
  :T    Store in variable T for next iteration.
}     End of apply loop.
`     Convert list to string.
Reto Koradi
fonte
4

JavaScript (ES6), 43 bytes

(l,u,v,p=0)=>v.map(c=>p=(p+=c)<l?l:p>u?u:p)

Define uma função anônima que recebe entrada no formato lower bound, upper bound, vector (as JS Array). Não sei se poderia ser mais curto, mas vou tentar. Sugestões são bem-vindas!

ETHproductions
fonte
4

Haskell, 37 bytes

u#l=tail.scanl(((min u.max l).).(+))0

Exemplo de uso: 6 # (-2) $ [1,4,3,-10,3,2,2,5,-4]-> [1,5,6,-2,1,3,5,6,2].

Comece a soma com 0para fixar os valores iniciais fora dos limites. Pegue no tailpara removê-lo do resultado final.

nimi
fonte
3

R, 61 bytes

function(x,l,u,s=0)sapply(x,function(i)s<<-min(u,max(l,s+i)))

sapplyé a função de aplicar uma função a todos os elementos de um vetor (aqui x), mas geralmente é feita em um contexto em que todas as avaliações são independentes e sem efeito colateral. Aqui, no entanto, eu uso o <<-operador para fazer uma atribuição no ambiente pai / chamada de sapplymodo que a soma acumulada spossa ser armazenada fora das avaliações iterativas. Esta é uma prática muito ruim ...

modelo
fonte
3

Mathematica, 46 bytes

Rest@FoldList[{a,b}Min[a+b,#2]~Max~#3,0,#]&

O personagem engraçado é U + F4A1 para \[Function]. Se o primeiro elemento puder estar no intervalo, eu poderia salvar 7 bytes.

LegionMammal978
fonte
3

Julia, 44 42 38 bytes

f(x,l,u,s=0)=[s=clamp(s+i,l,u)for i=x]

Isso cria uma função fque aceita uma matriz e dois números inteiros e retorna uma matriz.

Ungolfed:

function f(v::Array, u::Int, l::Int, s::Int = 0)
    # The parameter s is the cumulative sum, which begins
    # at 0

    # For each element i of v, define s to be s+i if
    # l ≤ s+i ≤ u, l if s+i < l, or u if s+i > u
    x = [s = clamp(s + i, l, u) for i = v]

    return x
end

Economizou 2 bytes usando a idéia da ETHproductions de incluir a soma cumulativa como parâmetro de função e 1 bytes graças a Glen O.

Alex A.
fonte
3

Python 2, 67 bytes

lambda u,l,v:reduce(lambda x,y:x+[max(min(x[-1]+y,u),l)],v,[0])[1:]
TFeld
fonte
2

Minkolang 0.9 , 30 bytes

0I3-[2g+d0c`,3&x0cd1c`3&x1cdN]

Isso, como função, assume que a pilha foi pré-inicializada para high, low, vector. O programa completo está abaixo ( 37 bytes ) e recebe a entrada como high, low, vector.

(n$I$)0I4-[2g+d0c`,3&x0cd1c`3&x1cdN].

Experimente aqui.

Explicação

(n$I$)                                   Read in integers from input until empty
      0                                  Initialize cumulative sum
       I4-[                        ]     Loop over vector
           2g+                           Get the next partial sum
              d0c`,3&x0c                 If too high, replace with high
                        d1c`3&x1cd       If too low, replace with low
                                  N      Output as integer
                                    .    Stop
El'endia Starman
fonte
1

C 98 bytes

É longo, mas funciona

#define P printf(
void c(*v,n,u,l,s,c){P"[");while(c++<n)s+=*v++,s=s<u?s>l?s:l:u,P"%d ",s);P"]");}

Exemplo de uso

#define P printf(
void c(*v,n,u,l,s,c) {
    P"[");
    while(c++<n)
        s+=*v++,s=s<u?s>l?s:l:u,P"%d ",s);
    P"]");
}

int main() {
    int vec[9] = {1, 4, 3, -10, 3, 2, 2, 5, -4};
    int upper = 6, lower = -2, count = 9;
    c(vec, count, upper, lower, 0, 0);
}

A saída seria

[1 5 6 -2 1 3 5 6 2 ]
Chris Loonam
fonte
1

APL, 29 27 18 bytes

Como Dennis apontou no bate-papo, \(expandir) funciona da esquerda para a direita, mas aplica a função que está sendo expandida da direita para a esquerda. Então não podemos simplesmente fazer 1↓(⎕⌈⎕⌊+)\0,⎕. Para solucionar isso, pegue o ,\da matriz e processe cada sub-matriz separadamente usando /(fold).

1↓(⎕⌈⎕⌊+)/¨⌽¨,\0,⎕

Entrada na ordem array, upper bound, lower bound.

lirtosiast
fonte