ベクトルの有界累積和を計算する


19

ベクトルの累積合計は、以前のすべての要素の合計を取得するだけで計算されます。例えば:

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]

ここで、上限と下限を課します。つまり、上限に達した場合は累積合計の増加を停止し、下限に達した場合は累積合計の減少を停止します。簡単な例:

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]

入力ベクトルは整数で構成され、必ずしもとだけでなく1-1正と負の両方で構成されます。と仮定しupper_lim >= lower_limます。ベクトルの最初の要素が境界の外側にある場合、境界に直接ジャンプします(最後の例を参照)。

入力として整数のベクトル、および上限と下限を表す2つの整数を受け取る関数を作成します。上で定義したように、制限付き累積ベクトルを出力します。入力は、関数の引数として、またはSTDINからのいずれかです。

標準コードのゴルフ規則が適用されます。

例:

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.

回答:


5

Pyth、14バイト

t.u@S+Q+NY1vwZ

オンラインで試す:デモンストレーションまたはテストスイート

説明

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バイト

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

オンラインで試す

これは、リストを最初の引数として、上限/下限のペアを2番目の2要素リストとして受け取ります。入力例:

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

最新バージョンでは、maxおよびmin操作を使用する代わりに、3つの値をソートし、中央の値を取得することで1バイトを節約します。これは、Jakubeのソリューションでも使用され、Martinによって提案されました。

説明:

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バイト

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

形式で入力を受け取る匿名関数を定義しますlower bound, upper bound, vector (as JS Array)。短くなるかどうかはわかりませんが、試してみます。提案を歓迎します!


4

Haskell、37バイト

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

使用例: 6 # (-2) $ [1,4,3,-10,3,2,2,5,-4] -> [1,5,6,-2,1,3,5,6,2]

合計を開始し0て、境界外の初期値を修正します。を取り、tail最終結果から削除します。


3

R、61バイト

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

sapplyは、ベクトルのすべての要素に関数を適用する関数です(ここx)が、通常はすべての評価が独立していて副作用のないコンテキストで実行されます。ただし、ここでは、<<-演算子を使用して、親/呼び出し環境で割り当てを行いsapply、累積s評価を反復評価の外部に保存できるようにします。これは非常に悪い習慣です...


3

Mathematica、46バイト

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

面白いキャラクターはU + F4A1です\[Function]。最初の要素が範囲内にあると想定できる場合、7バイト節約できます。


3

ジュリア、44 42 38バイト

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

これにより、f配列と2つの整数を受け取り、配列を返す関数が作成されます。

ゴルフをしていない:

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のアイデアとGlen Oのおかげで1バイトを使用して2バイトを節約しました。


3

Python 2、67バイト

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

2

Minkolang 0.9、30バイト

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

これは、関数として、スタックがに事前初期化されていることを前提としていますhigh, low, vector。完全なプログラムは以下(37バイト)で、入力をhigh, low, vector

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

ここで試してみてください。

説明

(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バイト

長いですが、動作します

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

使用例

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

出力は次のようになります

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

1

APL、29 27 18バイト

デニスがチャットで指摘したように、\(展開)は左から右に機能しますが、右から左に展開される関数を適用します。だから、私たちはただできない1↓(⎕⌈⎕⌊+)\0,⎕。これを回避するに,\は、配列を取得し、/(fold)を使用して各サブ配列を個別に処理します。

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

順番に入力してくださいarray, upper bound, lower bound

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.