Bir vektörün sınırlı kümülatif toplamını hesaplama


19

Bir vektörün kümülatif toplamı, sadece önceki tüm elemanların toplamı alınarak hesaplanır. Örneğin:

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]

Şimdi, bir üst ve bir alt sınır uygulayın, yani üst sınırdaysa kümülatif toplamı artırmayı ve alt sınırda ise kümülatif toplamı azaltmayı durdurursunuz. Basit bir örnek:

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]

Girdi vektörü, sadece 1ve aynı zamanda -1pozitif ve negatif olmak üzere tamsayılardan oluşur . Varsayın upper_lim >= lower_lim. Vektörün ilk elemanı sınırın dışındaysa, doğrudan sınıra atlayın (son örneğe bakın).

Bir tamsayı vektörünü girdi olarak alan bir işlev ve üst ve alt sınırları temsil eden iki tamsayı yazın. Yukarıda tanımlandığı gibi sınırlı kümülatif vektör çıktısı. Giriş, işlev bağımsız değişkenleri olarak veya STDIN'den olabilir.

Standart kod golf kuralları geçerlidir.

Örnekler:

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.

Yanıtlar:


5

Pyth, 14 bayt

t.u@S+Q+NY1vwZ

Çevrimiçi deneyin: Gösteri veya Test Paketi

açıklama

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 bayt

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

Çevrimiçi deneyin

Bu listeyi ilk argüman olarak, üst / alt limiti çifti ise ikinci 2 elemanlı liste olarak alır. Örnek girdi:

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

En son sürüm, bir maks ve min işlemi kullanmak yerine, 3 değeri sıralayarak ve orta değeri alarak 1 bayt kaydeder. Bu, Jakube'nin çözümünde de kullanıldı ve Martin tarafından önerildi.

Açıklama:

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 bayt

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

Girdi biçiminde alan anonim bir işlevi tanımlar lower bound, upper bound, vector (as JS Array). Daha kısa olabilir mi bilmiyorum, ama deneyeceğim. Öneriler hoş geldiniz!


4

Haskell, 37 bayt

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

Kullanım örneği: 6 # (-2) $ [1,4,3,-10,3,2,2,5,-4]->[1,5,6,-2,1,3,5,6,2] .

Başlangıç 0değerlerini sınırların dışına çıkarmak için toplamı ile başlatın. tailSon sonuçtan çıkarmak için kullanın.


3

R, 61 bayt

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

sapplybir vektörün her elemanına (burada x) bir fonksiyon uygulama fonksiyonudur, ancak genellikle tüm değerlendirmelerin bağımsız olduğu ve yan etkisi olmayan bir bağlamda yapılır. Ancak burada, kümülatif toplamın yinelemeli değerlendirmelerin dışında saklanabilmesi <<-için üst / çağrı ortamında bir atama yapmak için operatörü kullanıyorum . Bu çok kötü bir uygulama ...sapplys


3

Mathematica, 46 bayt

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

Komik karakter U + F4A1 için \[Function]. İlk öğenin aralıkta olduğu varsayılabilirse, 7 bayt tasarruf edebilirim.


3

Julia, 44 42 38 bayt

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

Bu bir işlev oluşturur f diziyi ve iki tamsayıyı kabul eden ve bir dizi döndüren bir .

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

ETHproductions'ın birikimli toplamı bir işlev parametresi olarak dahil etme fikrini ve Glen O sayesinde 1 bayt kullanarak 2 bayt kaydetti.


3

Python 2, 67 Bayt

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

2

Minkolang 0.9 , 30 bayt

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

Bu, bir işlev olarak, yığının önceden başlatılmış olduğunu varsayar high, low, vector. Tam program aşağıdadır ( 37 bayt ) ve girişi olarak alır high, low, vector.

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

Burada deneyin.

açıklama

(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 bayt

Uzun ama işe yarıyor

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

Kullanım örneği

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

Çıktı

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

1

APL, 29 27 18 bayt

Dennis'in sohbette işaret ettiği gibi, \(genişlet) soldan sağa çalışır, ancak genişletilen işlevi sağdan sola uygular. Yani sadece yapamayız 1↓(⎕⌈⎕⌊+)\0,⎕. ,\Diziyi alarak ve sonra /(fold) kullanarak her alt diziyi ayrı ayrı işleyerek bu sorunu gideririz .

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

Sırayla girin array, upper bound, lower bound.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.