Berechnen Sie die begrenzte kumulative Summe eines Vektors

19

Die kumulative Summe eines Vektors wird berechnet, indem einfach die Summe aller vorherigen Elemente genommen wird. Zum Beispiel:

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]

Legen Sie nun eine obere und eine untere Grenze fest. Dies bedeutet, dass Sie die kumulative Summe nicht mehr erhöhen, wenn sie sich an der oberen Grenze befindet, und die kumulative Summe nicht mehr verringern, wenn sie sich an der unteren Grenze befindet. Ein einfaches Beispiel:

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]

Der Eingabevektor besteht aus ganzen Zahlen, nicht notwendigerweise nur 1und -1sowohl positiven als auch negativen. Nimm das an upper_lim >= lower_lim. Wenn sich das erste Element des Vektors außerhalb der Grenze befindet, springen Sie direkt zur Grenze (siehe letztes Beispiel).

Schreiben Sie eine Funktion, die einen Vektor von Ganzzahlen als Eingabe verwendet, und zwei Ganzzahlen, die die oberen und unteren Grenzen darstellen. Geben Sie den begrenzten kumulativen Vektor wie oben definiert aus. Die Eingabe kann als Funktionsargument oder von STDIN erfolgen.

Es gelten die Standard-Code-Golfregeln.

Beispiele:

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
quelle

Antworten:

5

Pyth, 14 Bytes

t.u@S+Q+NY1vwZ

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung

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

CJam, 16 15 Bytes

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

Probieren Sie es online aus

Dies nimmt die Liste als erstes Argument und das Paar der oberen / unteren Grenze als zweite Liste mit 2 Elementen. Beispiel Eingabe:

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

Die neueste Version spart 1 Byte, indem die 3 Werte sortiert und der mittlere Wert verwendet wird, anstatt eine Max- und Min-Operation zu verwenden. Dies wurde auch in Jakubes Lösung verwendet, wie von Martin vorgeschlagen.

Erläuterung:

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

JavaScript (ES6), 43 Byte

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

Definiert eine anonyme Funktion, die Eingaben im Format entgegennimmt lower bound, upper bound, vector (as JS Array). Ich weiß nicht, ob es kürzer sein könnte, aber ich werde es versuchen. Vorschläge willkommen!

ETHproductions
quelle
4

Haskell, 37 Bytes

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

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

Beginnen Sie die Summe mit 0, um Anfangswerte außerhalb der Grenzen festzulegen. Nehmen Sie das tail, um es aus dem Endergebnis zu entfernen.

nimi
quelle
3

R, 61 Bytes

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

sapplyist die Funktion, um eine Funktion auf jedes Element eines Vektors anzuwenden (hier x), wird jedoch normalerweise in einem Kontext ausgeführt, in dem alle Auswertungen unabhängig und ohne Nebenwirkungen sind. Hier benutze ich jedoch den <<-Operator, um eine Zuordnung in der übergeordneten / aufrufenden Umgebung von vorzunehmen sapply, damit die kumulierte Summe saußerhalb der iterativen Auswertungen gespeichert werden kann. Das ist eine sehr schlechte Praxis ...

Flodel
quelle
3

Mathematica, 46 Bytes

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

Der lustige Charakter ist U + F4A1 für \[Function]. Wenn angenommen werden kann, dass das erste Element im Bereich liegt, könnte ich 7 Bytes einsparen.

LegionMammal978
quelle
3

Julia, 44 42 38 Bytes

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

Dadurch wird eine Funktion erstellt f, die ein Array und zwei Ganzzahlen akzeptiert und ein Array zurückgibt.

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

2 Bytes gespart durch die Idee von ETHproductions, die kumulierte Summe als Funktionsparameter und 1 Bytes dank Glen O einzubeziehen.

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

Minkolang 0,9 , 30 Bytes

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

Dies setzt in Abhängigkeit davon voraus, dass der Stack auf vorinitialisiert wurde high, low, vector. Das vollständige Programm liegt unter ( 37 Bytes ) und nimmt die Eingabe als high, low, vector.

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

Probieren Sie es hier aus.

Erläuterung

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

C 98 Bytes

Es ist lang, aber es funktioniert

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

Anwendungsbeispiel

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

Die Ausgabe wäre

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

APL, 29 27 18 Bytes

Wie Dennis im Chat betonte, \funktioniert (expandieren) von links nach rechts, wendet jedoch die Funktion an, die von rechts nach links erweitert wird. Also können wir es nicht einfach machen 1↓(⎕⌈⎕⌊+)\0,⎕. Wir ,\umgehen dies, indem wir das Array nehmen und dann jedes Subarray separat mit /(fold) verarbeiten.

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

Eingabe in der Reihenfolge array, upper bound, lower bound.

Lirtosiast
quelle