计算向量的有界累积和


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。如果向量的第一个元素在边界之外,请直接跳到边界(请参阅最后一个示例)。

编写一个函数,该函数将一个整数向量作为输入,并使用两个整数表示上限和下限。如上定义,输出有界累积向量。输入可以作为函数自变量,也可以来自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.

Answers:


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元素列表。输入示例:

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

最新版本通过对3个值进行排序并取中间值来节省1个字节,而不是使用max和min操作。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,该函数接受一个数组和两个整数并返回一个数组。

取消高尔夫:

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将累加和作为函数参数包括在内的思想,节省了2个字节;而由于Glen O,节省了1个字节。


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字节

正如Dennis在聊天中指出的那样,\(展开)从左到右起作用,但是应用从右到左展开的功能。所以我们不能只是做1↓(⎕⌈⎕⌊+)\0,⎕。我们通过采用,\数组的来解决此问题,然后使用/(fold)分别处理每个子数组。

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

按顺序输入array, upper bound, lower bound

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.