Calculer la somme cumulée bornée d'un vecteur

19

La somme cumulée d'un vecteur est calculée en prenant simplement la somme de tous les éléments précédents. Par exemple:

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]

Maintenant, imposez une limite supérieure et inférieure, ce qui signifie que vous arrêtez d'augmenter la somme cumulée si elle est à la limite supérieure et arrêtez de diminuer la somme cumulative si elle est à la limite inférieure. Un exemple simple:

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]

Le vecteur d'entrée est composé d'entiers, pas nécessairement uniquement 1et -1, à la fois positifs et négatifs. Supposons cela upper_lim >= lower_lim. Si le premier élément du vecteur est en dehors de la frontière, passez directement à la frontière (voir le dernier exemple).

Écrivez une fonction qui prend en entrée un vecteur d'entiers et deux entiers qui représentent les limites supérieure et inférieure. Sortez le vecteur cumulatif borné, comme défini ci-dessus. L'entrée peut être sous forme d'arguments de fonction ou de STDIN.

Les règles de golf du code standard s'appliquent.

Exemples:

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
la source

Réponses:

5

Pyth, 14 octets

t.u@S+Q+NY1vwZ

Essayez-le en ligne: démonstration ou suite de tests

Explication

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
la source
5

CJam, 16 15 octets

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

Essayez-le en ligne

Cela prend la liste comme premier argument et la paire de limite supérieure / inférieure comme deuxième liste à 2 éléments. Exemple d'entrée:

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

La dernière version enregistre 1 octet en triant les 3 valeurs et en prenant la valeur moyenne, au lieu d'utiliser une opération max et min. Cela a également été utilisé dans la solution de Jakube, ainsi que suggéré par Martin.

Explication:

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
la source
4

JavaScript (ES6), 43 octets

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

Définit une fonction anonyme qui accepte les entrées au format lower bound, upper bound, vector (as JS Array). Je ne sais pas si cela pourrait être plus court, mais je vais essayer. Bienvenue suggestions!

ETHproductions
la source
4

Haskell, 37 octets

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

Exemple d'utilisation: 6 # (-2) $ [1,4,3,-10,3,2,2,5,-4]-> [1,5,6,-2,1,3,5,6,2].

Commencez la somme avec 0pour fixer les valeurs initiales hors limites. Prenez le tailpour le supprimer du résultat final.

nimi
la source
3

R, 61 octets

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

sapplyest la fonction pour appliquer une fonction à chaque élément d'un vecteur (ici x) mais cela se fait généralement dans un contexte où toutes les évaluations sont indépendantes et sans effet secondaire. Ici, cependant, j'utilise l' <<-opérateur pour effectuer une affectation dans l'environnement parent / appelant de sapplysorte que la somme cumulée spuisse être stockée en dehors des évaluations itératives. C'est une très mauvaise pratique ...

flodel
la source
3

Mathematica, 46 octets

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

Le personnage drôle est U + F4A1 pour \[Function]. Si le premier élément peut être supposé être dans la plage, je pourrais économiser 7 octets.

LegionMammal978
la source
3

Julia, 44 42 38 octets

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

Cela crée une fonction fqui accepte un tableau et deux entiers et renvoie un tableau.

Non 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

Enregistrement de 2 octets en utilisant l'idée d'ETHproductions d'inclure la somme cumulée comme paramètre de fonction et 1 octet grâce à Glen O.

Alex A.
la source
3

Python 2, 67 octets

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

Minkolang 0.9 , 30 octets

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

Ceci, en tant que fonction, suppose que la pile a été pré-initialisée à high, low, vector. Le programme complet est ci-dessous ( 37 octets ) et prend l'entrée comme high, low, vector.

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

Essayez-le ici.

Explication

(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
la source
1

C 98 octets

C'est long, mais ça marche

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

Exemple d'utilisation

#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 sortie serait

[1 5 6 -2 1 3 5 6 2 ]
Chris Loonam
la source
1

APL, 29 27 18 octets

Comme Dennis l'a souligné dans le chat, \(développer) fonctionne de gauche à droite, mais applique la fonction en cours d'extension de droite à gauche. Nous ne pouvons donc pas simplement faire 1↓(⎕⌈⎕⌊+)\0,⎕. Nous contournons cela en prenant le ,\tableau, puis en traitant chaque sous-tableau séparément en utilisant /(fold).

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

Entrez dans l'ordre array, upper bound, lower bound.

lirtosiast
la source