Вычислить ограниченную совокупную сумму вектора


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.

Ответы:


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]

Последняя версия сохраняет 1 байт, сортируя 3 значения и принимая среднее значение вместо использования операций max и min. Это также было использовано в решении Якуба, а также предложено Мартином.

Объяснение:

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 которая принимает массив и два целых числа и возвращает массив.

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 байта с помощью идеи ETHproductions о включении накопленной суммы в качестве параметра функции и 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

Минколанг 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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.