Calcular la suma acumulativa acotada de un vector

19

La suma acumulativa de un vector se calcula simplemente tomando la suma de todos los elementos anteriores. Por ejemplo:

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]

Ahora, imponga un límite superior e inferior, lo que significa que deja de aumentar la suma acumulativa si está en el límite superior y deja de disminuir la suma acumulativa si está en el límite inferior. Un simple ejemplo:

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]

El vector de entrada consta de números enteros, no solo necesariamente 1y -1, tanto positivos como negativos. Asume eso upper_lim >= lower_lim. Si el primer elemento del vector está fuera del límite, salte directamente al límite (vea el último ejemplo).

Escriba una función que tome un vector de enteros como entrada, y dos enteros que representen los límites superior e inferior. Salida del vector acumulativo acotado, como se definió anteriormente. La entrada puede ser como argumentos de función o desde STDIN.

Se aplican reglas estándar de golf de código.

Ejemplos:

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
fuente

Respuestas:

5

Pyth, 14 bytes

t.u@S+Q+NY1vwZ

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación

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
fuente
5

CJam, 16 15 bytes

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

Pruébalo en línea

Esto toma la lista como primer argumento, y el par de límite superior / inferior como una segunda lista de 2 elementos. Entrada de ejemplo:

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

La última versión ahorra 1 byte al ordenar los 3 valores y tomar el valor medio, en lugar de utilizar una operación máxima y mínima. Esto también se usó en la solución de Jakube, así como lo sugirió Martin.

Explicación:

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
fuente
4

JavaScript (ES6), 43 bytes

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

Define una función anónima que toma entrada en el formato lower bound, upper bound, vector (as JS Array). No sé si podría ser más corto, pero lo intentaré. Sugerencias bienvenidas!

ETHproducciones
fuente
4

Haskell, 37 bytes

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

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

Comience la suma con 0para fijar los valores iniciales fuera de los límites. Tome tailpara eliminarlo del resultado final.

nimi
fuente
3

R, 61 bytes

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

sapplyes la función para aplicar una función a cada elemento de un vector (aquí x), pero generalmente se realiza en un contexto donde todas las evaluaciones son independientes y sin efectos secundarios. Aquí, sin embargo, utilizo el <<-operador para realizar una asignación en el entorno principal / de llamada de sapplymodo que la suma acumulativa sse pueda almacenar fuera de las evaluaciones iterativas. Esta es una muy mala práctica ...

flodel
fuente
3

Mathematica, 46 bytes

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

El personaje divertido es U + F4A1 para \[Function]. Si se puede suponer que el primer elemento está en el rango, podría guardar 7 bytes.

LegionMammal978
fuente
3

Julia, 44 42 38 bytes

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

Esto crea una función fque acepta una matriz y dos enteros y devuelve una matriz.

Sin golf:

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

Ahorré 2 bytes usando la idea de ETHproductions de incluir la suma acumulativa como parámetro de función y 1 bytes gracias a Glen O.

Alex A.
fuente
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
fuente
2

Minkolang 0.9 , 30 bytes

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

Esto, como función, supone que la pila se ha inicializado previamente high, low, vector. El programa completo está debajo ( 37 bytes ) y toma la entrada como high, low, vector.

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

Pruébalo aquí

Explicación

(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
fuente
1

C 98 bytes

Es largo, pero 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"]");}

Ejemplo 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);
}

La salida sería

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

APL, 29 27 18 bytes

Como Dennis señaló en el chat, \(expandir) funciona de izquierda a derecha, pero aplica la función que se expande de derecha a izquierda. Entonces no podemos simplemente hacer 1↓(⎕⌈⎕⌊+)\0,⎕. Trabajamos alrededor de esto tomando la ,\matriz y luego procesando cada subarreglo por separado usando /(fold).

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

Entrada en el orden array, upper bound, lower bound.

lirtosiast
fuente