Суми послідовних цілих чисел


27

Перш ніж хто-небудь скаже щось подібне і подібне . Але це не дура.


Деякі додатні цілі числа можуть бути записані як сума щонайменше двох послідовних натуральних чисел. Наприклад, 9=2+3+4=4+5. Напишіть функцію, яка приймає позитивне ціле число як свій вхід і друкує як свій вихід найдовшу послідовність збільшення послідовних позитивних цілих чисел, які підсумовуються їй (будь-який формат прийнятний, хоча -5 байт, якщо вихід є послідовністю збільшення, розділеною на, +як показано вище Якщо такої послідовності не існує, то саме номер слід надрукувати.

Це код гольфу. Діють стандартні правила. Найкоротший код у байтах виграє.


Зразки (зауважте, що форматування змінюється)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

Input:   25
Output:  [3,4,5,6,7]

2
Чи мають бути виведені числа у певному порядку (наприклад, збільшення)?
xnor

2
Чи повинні цифри бути> 0: 6 = 0 + 1 + 2 + 3 або 6 = 1 + 2 + 3
Демієн

5
Як зауваження, якщо існують тісно пов'язані виклики, кажучи, що "це не обман", мало що переконає людей у ​​цьому, якщо вони думають, що це дурня. Було б корисніше, якби ви пояснили, чому ви думаєте, що це не так.
Мартін Ендер

1
@Damien "позитивний" зазвичай означає> 0. Якщо 0 було включено, це називалося б "негативним".
Мартін Ендер

3
cc @Vixen ^ (також, якщо дозволено негативні числа, оптимальним рішенням завжди буде діапазон від -n+1до n)
Мартін Ендер

Відповіді:


11

Пітон, 67 байт

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+1],R[1:]][sum(R)>n])or R

Дивна пряма стратегія: пошук інтервалу R з потрібною сумою.

  • Якщо сума занадто мала, змістіть праву кінцеву точку інтервалу вгору, додавши наступне найбільше число.
  • Якщо сума занадто велика, підсуньте ліву кінцеву точку, видаливши найменший елемент
  • Якщо сума правильна, виведіть R.

Оскільки нижній кінець інтервалу лише збільшується, довші інтервали знаходяться перед більш короткими.


Як не дивно, також. Стек рекурсії з часом переповнюється, наприклад, n = 8192.
примо

7

Pyth, 12 10 байт

j\+hfqsTQ}M^SQ2

Код завдовжки 15 байт і відповідає бонусу -5 байт . Спробуйте його в Інтернеті в компіляторі Pyth .

Дякуємо @Jakube за те, що ти граєш на 2 байти!

Як це працює

j\+hfqsTQ}M^SQ2    (implicit) Store evaluated input in Q.

            S      Compute [1, ..., Q].
           ^  2    Get all pairs of elements of [1, ..., Q].
         }M        Reduce each pair by inclusive range. Maps [a, b] to [a, ..., b].
    f              Filter; for each pair T:
      sT             Add the integers in T.
     q  Q            Check if the sum equals Q.
                   Keep the pair if it does.
   h               Retrieve the first match.
                   Since the ranges [a, ..., b] are sorted by the value of a,
                   the first will be the longest, in ascending order.
j\+                Join, using '+' as separator.

1
Для тих із нас, хто не просвітлений в районі Піта, чи не могли б ви додати пояснення? :)
ETHproductions

Я відредагував свою відповідь.
Денніс

Дивовижне, дякую! Мені подобається ваша техніка.
ETHproductions

1
Введення 1000: 30 хвилин і підрахунок ...
примі

3

Математика, 73 68 65 56 43 байт

Cases[Range~Array~{#,#},i_/;Tr@i==#,{2},1]&

1
+1 Я закінчився подібним рішенням вчора ввечері, але мій Інтернет знизився. Також ви можете зробити Tuplesвираз інфіксації.
LegionMammal978

3

Haskell, 49 48 байт

f n=[[a..b]|a<-[1..n],b<-[a..n],sum[a..b]==n]!!0

1
1 байт для збереження: використовувати [...]!!0замість head[...].
німі

2

MATLAB, 87 79 байт

Я знаю, що відповідь MATLAB вже є, але ця суттєво відрізняється підходом.

x=input('');m=1:x;n=.5-m/2+x./m;l=max(find(~mod(n(n>0),1)));disp(m(1:l)+n(l)-1)

Це також працює на Octave . Ви можете спробувати онлайн тут . Я вже додав код consecutiveSum.mу пов'язану робочу область, тому просто введіть consecutiveSumу командному рядку, а потім введіть значення (наприклад, 25).

Я все ще працюю над тим, щоб зменшити його (можливо, трохи відкоригувавши рівняння), але в основному він знаходить найбільше значення, nдля якого mє ціле число, а потім відображає перші mчисла, починаючи з n.

То чому це працює? Ну в основному є математичне рівняння, яке регулює всі ці числа. Якщо ви вважаєте, що всі вони є послідовними, і починаєте з певного моменту, ви можете сказати:

n+(n+1)+(n+2)+(n+3)+...+(n+p)=x

Тепер, з цього стає очевидним, що послідовність - це в основному перші pчисла трикутника (включаючи 0'-е), додані до p+1безлічі n. Тепер, якщо ми дозволимо m=p+1, ми можемо сказати:

m*(n+(m-1)/2)==x

Це насправді досить вирішимо. Я все ще шукаю найкоротший спосіб кодування, у мене є ідеї, щоб спробувати зменшити вищевказаний код.


Для входу 25, вихід буде таким:

3     4     5     6     7

2
Що стосується вашої точки зору чисел трикутника, це завдання, по суті, намагається знайти трикутні числа з позитивною різницею вхідних даних, щоб індекси трикутних чисел у послідовності були 1,3,6,10,...максимальними.
Арктур

1

Python 2, 94 байти

n=input()
r=int((2*n)**.5)
while r:
 if~r%2*r/2==n%r:print range(n/r-~-r/2,n/r-~r/2);r=1
 r-=1

Введення взято з stdin. Це рішення підходить для дуже великих входів.

Це повторює можливі довжини рішення, r , маючи r ≤ √ (2n) , і чітко перевіряє рішення. Для того, щоб рішення існувало, якщо r непарне, n mod r повинен бути нульовим, а якщо r парним, n mod r повинен бути r / 2 .


Використання зразка

$ echo 8192 | python sum-con-int.py
[8192]

$ echo 1000002 | python sum-con-int.py
[83328, 83329, 83330, 83331, 83332, 83333, 83334, 83335, 83336, 83337, 83338, 83339]

$ echo 1000000006 | python sum-con-int.py
[250000000, 250000001, 250000002, 250000003]

Я навмисно обрав приклади з відносно невеликими результатами.


1

Октава, 89 байт

Це найкраще, що я міг зробити в Октаві. Алгоритм такий самий, як у xnor.

x=input('');k=i=1;while x;s=sum(k:i);if s<x;i++;elseif s>x;k++;else;x=0;end;end;disp(k:1)

У MATLAB це буде 95 байт:

x=input('');k=1;i=1;while x;s=sum(k:i);if s<x;i=i+1;elseif s>x;k=k+1;else x=0;end;end;disp(k:i)

У MATLAB це працює приблизно за 0,1 секунди для введення 2000000та 1 секунду для введення 1000002.


1

awk, 51 байт

{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j

Код - 56 байт, мінус 5 байт для вихідного формату. Мені довелося використовувати 4 додаткові байти, щоб створити цей формат, тому я фактично врятував 1 байт. Ура! ;)

Це насправді робить важку роботу підбиття підсумків, починаючи з 1, поки сума не перевищує вхідний. Потім він починає віднімати числа, починаючи з 1, поки число не буде меншим, ніж вхідне. Він продовжує таким чином змінювати початковий і кінцевий номер, поки не знайде результат, який потім надрукує.

Приклад використання

echo 303 | awk '{while($0!=s+=s<$0?++j:-++i);while(++i-j)r=r i"+"}$0=r j'

Виведення прикладу

48 + 49 + 50 + 51 + 52 + 53

Я спробував це для введення, 1e12і це дало правильний результат ( 464562+...+1488562) майже відразу. Хоча, звичайно, знадобилося певний друк ...


Любіть підхід Awk. У мене виникають труднощі при розробці порядку пріоритетності в палітурках. Чи не заперечуєте, будь ласка, включіть версію з доданими ще круглими дужками, щоб зробити її трохи очевиднішою? :)
Wildcard

1
Сподіваюсь, це допомагає: {while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j я завжди останнє ціле число, яке відняли від початку ланцюга, j завжди останнє ціле число, додане в кінці ланцюжка
Cabbie407

0

Japt , 33 байти

Тут використовується техніка Denth's Pyth , хоча це значно довше ...

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU

Спробуйте в Інтернеті! Попередження: Для великих входів (<= 20) потрібно тривати деякий час, і заморозить веб-переглядач, поки це не зробиться.

Необурені і пояснення

1oU à2 £    W=Xg o1+Xg1¹ x ¥ U© W} rª  ª U
1oU à2 mXYZ{W=Xg o1+Xg1) x ==U&&W} r|| ||U

          // Implicit: U = input integer
1oU à2    // Generate a range from 1 to U, and take all combinations of length 2.
mXYZ{     // Map each item X in this range to:
W=Xg o    //  Set variable W to the range of integers starting at the first item in X,
1+Xg1)    //  and ending at 1 + the second item in X.
x ==U&&W  //  If the sum of this range equals U, return W; otherwise, return false.
r||       // Reduce the result with the || operator, returning the first non-false value.
||U       // If this is still false, there are no consecutive ranges that sum to U,
          // so resort to U itself.
          // Implicit: output last expression

Версія за заробіток: (38 байт - 5 = 33)

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU² q'+

0

Джулія, 92 байти

x->(t=filter(i->all(j->j==1,diff(sort(i))),partitions(x));collect(t)[indmax(map(length,t))])

Це анонімна функція, яка приймає ціле число і повертає масив. Щоб зателефонувати, дайте ім’я, наприклад f=x->....

Безголівки:

function f(x::Integer)
    # Get all arrays of integers that sum to x
    p = partitions(x)

    # Filter these down to only consecutive runs by checking whether
    # all differences are 1
    t = filter(i -> all(j -> j == 1, diff(sort(i))), p)

    # Find the index of the longest element of t
    i = indmax(map(length, t))

    return collect(t)[i]
end

0

Рубін, 94 байти

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}

Безголівки:

-> n {
  ([*1..n].permutation(2).map { |i,j|   # Finds all the possible sets of size 2
     [*i..j] if(i..j).reduce(:+) == n   # Adds a set to an array if sum of the set is n.
   }-[p]                                # Removes nil from the array
  ).max_by { |k|                        # Finds the longest sequence
    k.size
  } || n                                # Returns n if no sequence found.
}

Використання:

->n{([*1..n].permutation(2).map{|i,j|[*i..j]if(i..j).reduce(:+)==n}-[p]).max_by{|k|k.size}||n}[25]
=> [3, 4, 5, 6, 7]

0

Серйозно, 53 - 5 = 48 байт

,;;;╝`;u@n╟(D;)`n(XXk`iu@u@x;Σ╛=[])Ii`╗`ñ╜M`M;░p@X'+j

Шестнадцятковий дамп

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

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

Це підхід грубої сили, подібний до Пінта Денніса.

Все, kщойно зачитує вхід nв регістр 1, а потім створює список [[1],[2,2],[3,3,3],[4,4,4,4],...]до n n's.

Наступний біт до - це функція, збережена в регістрі 0, яка займає пару, збільшує обидва елементи, перетворює їх у діапазон, знаходить суму діапазону та перевіряє, чи є ця сума значенням у регістрі 1. Якщо це, він повертає відповідний діапазон, а якщо його немає, він повертає порожній список.

Частина до останнього появи Mкарт відображає функцію над вигадливим списком описаних вище списків, роблячи enumerateв кожному списку, а потім відображаючи збережену функцію над ним. Коли це зроблено, у нас є список списків, кожен з яких порожній, або діапазон, який підсумовує n.

;░видаляє порожні списки. p@Xбере перший список, який залишається ( 0@Eтакож працював би). '+jставиться +між кожним номером, оскільки він перетворює список у рядок для премії.


0

ES6, 72 байти

n=>{for(l=u=1;n;)n>0?n-=u++:n+=l++;return[...Array(u).keys()].slice(l);}

Прямий порт розкішного рішення @ Cabbie407, але без бонусу за форматування, оскільки тут це штраф.


0

Python 3, 239 236 215 203 байт

Це трохи громіздко. Мені доведеться пізніше пограти в гольф.

def x(n):
 r=[n]
 for i in range(2,n):
  t=[]
  if i%2*(n%i<1):t=[j+n//i-i//2for j in range(i)]
  elif i%2<1and n%i==i//2:t=[j+n//i-i//2+1for j in range(i)]
  if t[:1]>[0]*(sum(t)==n):r+=t,
 return r[-1]

Це kтому, що якщо ви перевіряєте t[0]на порожній t, Python видає на вас грубі шуми. Знову ж таки, це потребує гольфу. Завдяки t[:1], більше немає грубих шумів! Вам просто потрібно перевірити інший масив.


0

Желе , 8 байт (неконкуренто)

ẆS⁼¥Ðf⁸Ṫ

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

Якщо я правильно розумію, це може бути версія (11-5 = 6) -байтів:

ẆS⁼¥Ðf⁸Ṫj”+

Заради інтересів, існує 12 подібних рішень (включаючи це) шляхом заміни невекторизуючих рівних для векторизуючих рівних, зміни лівого аргументу на перший аргумент або ідентичності та заміни рівних на нерівні та фільтрування для фільтрування як для векторизації, так і для невекторизації. : O
HyperNeutrino

Скажімо, я розмістив той, який має найбільш сенс, але з оптимізацією швидкості.
Ерік Аутгольфер


0

PHP, 70 байт

while(fmod($q=sqrt(2*$argn+(++$p-.5)**2)-.5,1));print_r(range($p,$q));

Запустіть як трубу -nRабо спробуйте в Інтернеті .

з кроком, pпоки не знайде ціле рішення для argument==(p+q)*(q-p+1)/2,
а потім надрукує діапазон від pдо q.


0

Excel VBA, 119 - 5 = 114 байт

Subnпорядок, який приймає введення очікуваного цілого типу і виводить найдовшу послідовність послідовних чисел, які підсумовують його до комірки[A1]

Sub a(n)
For i=1To n
s=0
For j=i To n
s=s+j
If s=n Then:For k=i To j-1:r=r &k &"+":Next:[A1]=r &j:End
Next
Next
End Sub
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.