Суммы последовательных целых чисел


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

Python, 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
Для тех из нас, кто не является просвещенным в области Pyth, не могли бы вы объяснить, пожалуйста? :)
ETHproductions

Я отредактировал свой ответ.
Деннис

Круто, спасибо! Мне нравится твоя техника.
ETHproductions

1
Ввод 1000: 30 минут и подсчет ...
прим

3

Mathematica, 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[...].
Nimi

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)

Это также работает в Октаве . Вы можете попробовать онлайн здесь . Я уже добавил код consecutiveSum.mв связанную рабочую область, поэтому просто введите consecutiveSumв командной строке, а затем введите значение (например, 25).

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

Так почему это работает? Ну, в основном есть математическое уравнение, управляющее всеми этими числами. Если вы считаете, что все они являются последовательными и начинают с какого-то момента, вы можете сказать:

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

Теперь, от этого становится очевидным , что последовательность в основном только первые pцифры треугольника ( в том числе 0'th), добавленные к 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

Ввод взят из стандартного ввода. Это решение подходит для очень больших входов.

Он перебирает возможные длины решения 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 я всегда
являюсь

0

Japt , 33 байта

Это использует технику Денниса Пита , хотя это значительно дольше ...

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->... .

Ungolfed:

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}

Ungolfed:

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

Попробуйте онлайн!

Это подход грубой силы, похожий на Pyth Денниса.

Все до kсчитывания вводит nв регистр 1, а затем создает список [[1],[2,2],[3,3,3],[4,4,4,4],...]до n n.

Следующий бит - это функция, хранящаяся в регистре 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);}

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


0

Питон 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

Допустим, я разместил тот, который имеет больше смысла, но с оптимизацией скорости.
Эрик Outgolfer

0

05AB1E , 11 - 5 = 6 байтов (не конкурирующие)

Принимая этот бонус, конечно :)

LŒʒOQ}é¤'+ý

Попробуйте онлайн!

LŒʒOQ}é¤'+ý  Argument: n
LΠ          Sublists of range 1 to n
  ʒOQ}       Filter by total sum equals n
      é¤     Get longest element
        '+ý  Join on '+'

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 байт

Subподпрограмма, которая принимает ввод nцелого числа ожидаемого типа и выводит самую длинную последовательность последовательных чисел, которые суммируются в ячейке[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.