Обчисліть обмежену сукупну суму вектора


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

Піт, 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}`

Спробуйте в Інтернеті

Це сприймає список як перший аргумент, а пара верхньої / нижньої межі - як другий список з двома елементами. Приклад введення:

[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

Хаскелл, 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

Математика, 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

Збережено 2 байти за допомогою ідеї ETHproductions про включення сукупної суми як функціонального параметра та 1 байт завдяки Глен О.


3

Пітон 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,⎕. Ми ,\вирішуємо це, беручи масив, а потім обробляємо кожний підмасив окремо, використовуючи /(скласти).

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

Введіть у порядку array, upper bound, lower bound.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.