Sumy kolejnych liczb całkowitych

27

Zanim ktokolwiek powie coś podobnego i podobnego . Ale to nie jest dupek.


Niektóre dodatnie liczby całkowite można zapisać jako sumę co najmniej dwóch kolejnych liczb całkowitych dodatnich. Na przykład 9=2+3+4=4+5. Napisz funkcję, która przyjmuje na wejściu dodatnią liczbę całkowitą i wypisuje jako wynik najdłuższą sekwencję rosnących kolejnych liczb całkowitych dodatnich, które się do niej sumują (dopuszczalny jest dowolny format, chociaż -5 bajtów, jeśli wynikiem jest sekwencja rosnąca oddzielona, +jak pokazano powyżej Jeśli nie ma takiej sekwencji, należy wydrukować sam numer.

To jest kod golfowy. Obowiązują standardowe zasady. Najkrótszy kod w bajtach wygrywa.


Próbki (pamiętaj, że formatowanie jest różne)

Input:   9
Output:  2,3,4

Input:   8
Output:  8

Input:   25
Output:  [3,4,5,6,7]
Arktur
źródło
2
Czy wyprowadzane liczby muszą być w określonej kolejności (np. Rosnące)?
xnor
2
Czy liczby muszą być> 0: 6 = 0 + 1 + 2 + 3 lub 6 = 1 + 2 + 3
Damien,
5
Na marginesie, jeśli istnieją ściśle powiązane wyzwania, powiedzenie „to nie jest dupek” niewiele zrobi, aby przekonać ludzi o tym, jeśli uważają, że to duplikat. Przydałoby się wyjaśnienie, dlaczego uważasz, że tak nie jest.
Martin Ender,
1
@Damien „pozytywny” zwykle oznacza> 0. Jeśli podano 0, nazwano by to „nieujemnym”.
Martin Ender,
3
cc @Vixen ^ (także jeśli dozwolone byłyby liczby ujemne, optymalnym rozwiązaniem zawsze byłby zakres od -n+1do n)
Martin Ender

Odpowiedzi:

11

Python, 67 bajtów

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

Dziwnie prosta strategia: wyszukaj przedział R z właściwą sumą.

  • Jeśli suma jest zbyt mała, przesuń prawy punkt końcowy interwału w górę o jeden, dodając następną najwyższą liczbę.
  • Jeśli suma jest zbyt duża, przesuń lewy punkt końcowy w górę, usuwając najmniejszy element
  • Jeśli suma jest poprawna, wyślij R.

Ponieważ dolny koniec przedziału tylko się zwiększa, dłuższe przedziały znajdują się przed krótszymi.

xnor
źródło
Dziwnie też wydajne. Stos rekurencyjny ostatecznie się przepełnia, np. N = 8192.
primo,
7

Pyth, 12 10 bajtów

j\+hfqsTQ}M^SQ2

Kod ma 15 bajtów i kwalifikuje się do premii -5 bajtów . Wypróbuj online w kompilatorze Pyth .

Dzięki @Jakube za grę w golfa z 2 bajtów!

Jak to działa

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.
Dennis
źródło
1
Czy dla tych z nas, którzy nie są oświeceni w dziedzinie Pyth, proszę podać wyjaśnienie? :)
ETHproductions
Zredagowałem swoją odpowiedź.
Dennis,
Wielkie dzieki! Lubię twoją technikę.
ETHproductions
1
Wprowadź 1000: 30 minut i wciąż trwa ...
primo
3

Mathematica, 73 68 65 56 43 bajty

Cases[Range~Array~{#,#},i_/;Tr@i==#,{2},1]&
alephalpha
źródło
1
+1 Ostatniej nocy znalazłem podobne rozwiązanie, ale mój internet się zepsuł. Możesz także wykonać Tupleswyrażenie infiksowe.
LegionMammal978,
3

Haskell, 49 48 bajtów

f n=[[a..b]|a<-[1..n],b<-[a..n],sum[a..b]==n]!!0
Damien
źródło
1
1 bajt do zapisania: użyj [...]!!0zamiast head[...].
nimi
2

MATLAB, 87 79 bajtów

Wiem, że jest już odpowiedź MATLAB, ale ta jest znacznie inna w podejściu.

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)

Działa to również na Octave . Możesz spróbować online tutaj . Dodałem już kod do consecutiveSum.mpołączonego obszaru roboczego, więc po prostu wpisz consecutiveSumw wierszu polecenia, a następnie wprowadź wartość (np. 25).

Nadal pracuję nad zmniejszeniem go (być może nieco poprawionym stosowanym równaniem), ale w zasadzie znajduje największą wartość, ndla której mjest liczbą całkowitą, a następnie wyświetla pierwsze mliczby zaczynające się od n.

Dlaczego to działa? Zasadniczo istnieje matematyczne równanie rządzące tymi wszystkimi liczbami. Jeśli uważasz, że wszystkie są następujące po sobie i zaczynasz od pewnego momentu, możesz w zasadzie powiedzieć:

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

Teraz z tego wynika, że ​​sekwencja jest w zasadzie tylko pierwszymi pnumerami trójkątów (w tym 0), dodanymi do p+1wielu n. Teraz, jeśli pozwolimy m=p+1, możemy powiedzieć:

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

W rzeczywistości jest to całkiem możliwe do rozwiązania. Wciąż szukam najkrótszego sposobu na zrobienie tego, mam kilka pomysłów, aby spróbować zredukować powyższy kod.


Dla wejścia 25 wynik będzie:

3     4     5     6     7
Tom Carpenter
źródło
2
Jeśli chodzi o twoje zdanie na temat liczb trójkątów, to wyzwanie polega zasadniczo na znalezieniu liczb trójkątnych z dodatnią różnicą danych wejściowych, tak aby wskaźniki liczb trójkątnych w sekwencji były 1,3,6,10,...zmaksymalizowane.
Arcturus,
1

Python 2, 94 bajty

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

Dane wejściowe są pobierane ze standardowego wejścia. To rozwiązanie jest odpowiednie dla bardzo dużych nakładów.

Powoduje to iterację możliwych długości rozwiązania, r , mających r ≤ √ (2n) , i wyraźnie sprawdza rozwiązanie. Aby istniało rozwiązanie, jeśli r jest nieparzyste, n mod r musi wynosić zero, a jeśli r jest parzyste, n mod r musi być r / 2 .


Przykładowe użycie

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

Celowo wybrałem przykłady o stosunkowo niewielkich wynikach.

primo
źródło
1

Oktawa, 89 bajtów

To najlepsze, co mogłem zrobić w Octave. Algorytm jest taki sam jak 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)

W MATLAB byłoby to 95 bajtów:

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)

W MATLAB trwa to około 0,1 sekundy na wejście 2000000i 1 sekundę na wejście 1000002.

Stewie Griffin
źródło
1

awk, 51 bajtów

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

Kod ma 56 bajtów, minus 5 bajtów dla formatu wyjściowego. Musiałem użyć 4 dodatkowych bajtów, aby wygenerować ten format, więc faktycznie zapisałem 1 bajt. Brawo! ;)

To naprawdę ciężka praca sumowania, zaczynając od 1, aż suma jest większa niż wkład. Następnie zaczyna odejmować liczby, zaczynając od 1, aż liczba będzie mniejsza niż wartość wejściowa. W ten sposób zmienia numer początkowy i końcowy do momentu znalezienia wyniku, który następnie drukuje.

Przykład użycia

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

Wyjście z przykładu

48 + 49 + 50 + 51 + 52 + 53

Próbowałem tego dla danych wejściowych 1e12i 464562+...+1488562prawie natychmiast uzyskało prawidłowy wynik ( ). Chociaż wydrukowanie go zajęło trochę czasu ...

Cabbie407
źródło
Uwielbiam podejście Awk. Mam problem z ustaleniem kolejności pierwszeństwa w powiązaniach. Czy miałbyś coś przeciwko dołączeniu wersji z większą liczbą nawiasów, aby uczynić ją nieco bardziej oczywistą? :)
Wildcard
1
Mam nadzieję, że to pomaga: {while($0!=s)s+=(s<$0) ? (++j) : -(++i); while(++i<j)r=r i"+"}$0=r j i jest zawsze ostatnią liczbą całkowitą odejmowaną od początku łańcucha, j jest zawsze ostatnią liczbą całkowitą dodaną na końcu łańcucha
Cabbie407
0

Japt , 33 bajty

Wykorzystuje technikę Pythona Dennisa , chociaż jest znacznie dłuższa ...

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

Wypróbuj online! Ostrzeżenie: w przypadku większych danych wejściowych (<= 20) zakończenie zajmuje trochę czasu i zawiesza przeglądarkę, aż to zrobi.

Bez golfa i wyjaśnienia

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

Wersja premiowa: (38 bajtów - 5 = 33)

1oU à2 £W=Xg o1+Xg1¹x ¥U©W} rª ªU² q'+
ETHprodukcje
źródło
0

Julia, 92 bajty

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

Jest to anonimowa funkcja, która przyjmuje liczbę całkowitą i zwraca tablicę. Aby to nazwać, nadaj mu nazwę, np f=x->....

Nie golfowany:

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
Alex A.
źródło
0

Ruby, 94 bajty

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

Nie golfowany:

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

Stosowanie:

->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]
Vasu Adari
źródło
0

Poważnie, 53-5 = 48 bajtów

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

Hex Dump

2c3b3b3bbc603b75406ec728443b29606e2858586b60697540754
0783be4be3d5b5d29496960bb60a4bd4d604d3bb0704058272b6a

Wypróbuj online!

To podejście brutalnej siły, podobne do Pyth Dennisa.

Wszystko po kprostu odczytuje dane wejściowe ndo rejestru 1, a następnie tworzy listę [[1],[2,2],[3,3,3],[4,4,4,4],...]do n n.

Następny bit do to funkcja zapisana w rejestrze 0, która bierze parę, inkrementuje oba elementy, konwertuje je na zakres, znajduje sumę zakresu i sprawdza, czy suma ta jest wartością w rejestrze 1. Jeśli tak, zwraca odpowiedni zakres, a jeśli nie, zwraca pustą listę.

Część do ostatniego wystąpienia Mmapuje funkcję na fantazyjnej liście list opisanej powyżej, wykonując enumeratekażdą listę, a następnie mapując na niej zapisaną funkcję. Kiedy to nastąpi, mamy listę list, z których każda jest pusta lub zakres, który sumuje się n.

;░usuwa puste listy. p@Xpobiera pierwszą listę, która pozostaje ( 0@Ebędzie również działać). '+jumieszcza +między każdą liczbą, gdy konwertuje listę na ciąg znaków premii.

kwintopia
źródło
0

ES6, 72 bajty

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

Prosty port rozwiązania awk @ Cabbie407, ale bez premii za formatowanie, ponieważ tutaj jest to kara.

Neil
źródło
0

Python 3, 239 236 215 203 bajtów

To trochę kłopotliwe. Później będę musiał zagrać w golfa.

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]

Wynika kto z faktu, że jeśli zaznaczysz t[0]puste t, Python wydaje ci niegrzeczny dźwięk. To znowu wymaga gry w golfa. Dzięki t[:1], nigdy więcej niegrzecznych dźwięków! Musisz tylko porównać z inną tablicą.

Sherlock9
źródło
0

Galaretka , 8 bajtów (niekonkurencyjna)

ẆS⁼¥Ðf⁸Ṫ

Wypróbuj online!

Jeśli dobrze rozumiem, może to być wersja (11-5 = 6) bajtów:

ẆS⁼¥Ðf⁸Ṫj”+
Erik the Outgolfer
źródło
Ze względu na zainteresowanie istnieje 12 podobnych rozwiązań (w tym jedno) poprzez zamianę nie wektoryzujących równań dla wektoryzacji równych, zamianę lewego argumentu na pierwszy argument lub tożsamość oraz zamianę równości na nie-równe i filtrowanie dla filtrowanie zarówno wektoryzacji, jak i wektoryzacji. : O
HyperNeutrino
Załóżmy, że opublikowałem ten, który ma największy sens, ale z optymalizacją prędkości.
Erik the Outgolfer
0

05AB1E , 11-5 = 6 bajtów (niekonkurujące)

Biorąc ten bonus oczywiście :)

LŒʒOQ}é¤'+ý

Wypróbuj online!

LŒʒOQ}é¤'+ý  Argument: n
LŒ           Sublists of range 1 to n
  ʒOQ}       Filter by total sum equals n
      é¤     Get longest element
        '+ý  Join on '+'
kalsowerus
źródło
0

PHP, 70 bajtów

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

Uruchom jako potok z -nRlub spróbuj online .

zwiększa, pdopóki nie znajdzie rozwiązania dla liczby całkowitej argument==(p+q)*(q-p+1)/2,
a następnie drukuje zakres od pdo q.

Tytus
źródło
0

Excel VBA, 119-5 = 114 bajtów

Subprocedura, która pobiera nliczbę całkowitą oczekiwanego typu i wysyła najdłuższą sekwencję kolejnych liczb, które sumują się do komórki[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
Taylor Scott
źródło