Calcola la somma cumulativa limitata di un vettore


19

La somma cumulativa di un vettore viene calcolata semplicemente prendendo la somma di tutti gli elementi precedenti. Per esempio:

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]

Ora, imponi un limite superiore e uno inferiore, il che significa che smetti di aumentare la somma cumulativa se si trova al limite superiore e smetti di diminuire la somma cumulativa se si trova al limite inferiore. Un semplice esempio:

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]

Il vettore di input è composto da numeri interi, non necessariamente solo 1e -1, sia positivi che negativi. Supponiamo che upper_lim >= lower_lim. Se il primo elemento del vettore è al di fuori del limite, passa direttamente al limite (vedi l'ultimo esempio).

Scrivi una funzione che accetta come input un vettore di numeri interi e due numeri interi che rappresentano i limiti superiore e inferiore. Emette il vettore cumulativo limitato, come definito sopra. L'input può essere come argomento di funzione o da STDIN.

Si applicano le regole standard per il golf.

Esempi:

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.

Risposte:


5

Pyth, 14 byte

t.u@S+Q+NY1vwZ

Provalo online: dimostrazione o Test Suite

Spiegazione

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

5

CJam, 16 15 byte

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

Provalo online

Questo prende l'elenco come primo argomento e la coppia di limite superiore / inferiore come secondo elenco di 2 elementi. Esempio di input:

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

L'ultima versione salva 1 byte ordinando i 3 valori e prendendo il valore medio, invece di utilizzare un'operazione massima e minima. Questo è stato anche usato nella soluzione di Jakube, così come suggerito da Martin.

Spiegazione:

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.

4

JavaScript (ES6), 43 byte

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

Definisce una funzione anonima che accetta input nel formato lower bound, upper bound, vector (as JS Array). Non so se potrebbe essere più breve, ma ci proverò. Suggerimenti benvenuti!


4

Haskell, 37 byte

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

Esempio di utilizzo: 6 # (-2) $ [1,4,3,-10,3,2,2,5,-4]-> [1,5,6,-2,1,3,5,6,2].

Inizia la somma con 0per correggere i valori iniziali fuori dai limiti. Prendi il tailper rimuoverlo dal risultato finale.


3

R, 61 byte

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

sapplyè la funzione per applicare una funzione a ogni elemento di un vettore (qui x) ma di solito viene eseguita in un contesto in cui tutte le valutazioni sono indipendenti e senza effetti collaterali. Qui, tuttavia, utilizzo l' <<-operatore per eseguire un'assegnazione nell'ambiente padre / chiamante in sapplymodo che la somma cumulativa spossa essere archiviata al di fuori delle valutazioni iterative. Questa è una brutta pratica ...


3

Mathematica, 46 byte

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

Il personaggio divertente è U + F4A1 per \[Function]. Se si può presumere che il primo elemento sia compreso nell'intervallo, è possibile salvare 7 byte.


3

Julia, 44 42 38 byte

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

Ciò crea una funzione fche accetta un array e due numeri interi e restituisce un array.

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

Hai salvato 2 byte usando l'idea di ETHproductions di includere la somma cumulativa come parametro di funzione e 1 byte grazie a Glen O.


3

Python 2, 67 byte

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

2

Minkolang 0.9 , 30 byte

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

Questo, come funzione, presuppone che lo stack sia stato pre-inizializzato high, low, vector. Il programma completo è inferiore ( 37 byte ) e accetta input come high, low, vector.

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

Provalo qui.

Spiegazione

(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

1

C 98 byte

È lungo, ma funziona

#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"]");}

Esempio di utilizzo

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

L'output sarebbe

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

1

APL, 29 27 18 byte

Come ha sottolineato Dennis in chat, \(espandi) funziona da sinistra a destra, ma applica la funzione che viene espansa con da destra a sinistra. Quindi non possiamo semplicemente fare 1↓(⎕⌈⎕⌊+)\0,⎕. Per ovviare a questo, prendiamo l' ,\array e quindi elaboriamo ciascun subarray separatamente usando /(fold).

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

Inserisci nell'ordine array, upper bound, lower bound.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.