Die Summe der aufeinanderfolgenden ungeraden Zahlen


24

Obwohl verwandte Herausforderungen gestellt wurden, ist dies eine andere, um seine eigene Frage zu rechtfertigen.


Herausforderung

Bei einer positiven Ganzzahl wird die längste Folge aufeinanderfolgender positiver ungerader Ganzzahlen zurückgegeben, deren Summe die angegebene Ganzzahl ist. Wenn eine solche Sequenz nicht vorhanden ist, können Sie einen Fehler in einer für Ihre Sprache sinnvollen Weise melden, einschließlich der Rückgabe eines falschen Werts oder der Auslösung einer Ausnahme.

Testfälle

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (beachte, dass [9] keine gültige Antwort ist)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (beachte, dass [51, 53] keine gültige Antwort ist)

Wertung

Das ist , also gewinnt die kürzeste Antwort in jeder Sprache.


2
Kann mein Programm nur für immer laufen, wenn es keine Lösung gibt?
Dennis

Sehr verwandt . Die Tatsache, dass einige gerade Zahlen in diesem nicht dargestellt werden können, könnte es jedoch davor bewahren, betrogen zu werden.
ETHproductions

6
Können 15 nicht [-1, 1, 3, 5, 7] geben? Wenn nur positive Werte zulässig sind, sollten Sie dies angeben.
xnor

2
@ ЕвгенийНовиков Sie übersprungen 17
kalsowerus

1
@ kalsowerus ja. Ich verstehe das Wort "konsekutiv" falsch
Евгений Новиков

Antworten:


11

Haskell, 67 65 63 62 58 Bytes

4 Bytes gespart dank Julian Wolf

f x=[[2*n+1,2*n+3..2*m]|n<-[0..x],m<-[n..x],m^2-n^2==x]!!0

Probieren Sie es online!

Ich überprüfen , ob die Zahl kann als er Differenz von zwei Quadraten ausgedrückt werden: m^2-n^2. Ich kann dann die Liste der aufeinanderfolgenden ungeraden Zahlen konstruieren: [2n+1,2n+3...2m-1]. Beachten Sie, dass ndie längste Liste ausgegeben wird , da das Minimum ausgewählt ist


7
Down-Voter: Es wäre sowohl freundlicher als auch konstruktiver, einen Kommentar mit einer Begründung hinzuzufügen, insbesondere wenn Sie einen neuen Benutzer down-voten.
Jonathan Allan

1
Sofern ich nichts vermisse, können Sie 4 Bytes sparen, indem Sie nur xfür beide nundm
Julian Wolf

Nur damit Sie wissen, wurde die Downvote automatisch vom Community-Benutzer abgegeben, als Sie Ihre Antwort bearbeitet haben. Ich halte das für einen Bug . (CC @ JonathanAllan)
Dennis

Ahh, es war einer von denen.
Jonathan Allan

9

Python 2 , 66 62 Bytes

f=lambda n,k=0,*r:n-sum(r)and f(n,k+1,*range(k%n|1,k/n,2))or r

Beendet mit einem RuntimeError (maximale Rekursionstiefe überschritten), wenn es keine Lösung gibt.

Probieren Sie es online!


1
Wenn die Eingabewerte hoch genug sind, es jedoch eine Lösung gibt, führt dies zu einem RuntimeError ?
Okx

Wenn das Rekursionslimit nicht hoch genug ist und / oder der Stapel nicht groß genug ist, ja. Es ist jedoch üblich, physische Einschränkungen zu ignorieren (z. B. muss eine C-Antwort nur für 32-Bit-Eingaben funktionieren), und das OP hat ausdrücklich erklärt, dass ein ewiges Laufen akzeptabel ist, wenn es keine Lösung gibt.
Dennis

9

Jelly ,  11 bis  10 Bytes

-1 Byte dank Dennis (benutze das implizite Range Building von - ersetzen Rm2Ẇdurch ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Ein monadischer Link, der nach Möglichkeit eine Liste der Summanden zurückgibt oder 0nicht.

Probieren Sie es online!

Wie?

ẆḤ’S_¥Ðḟ⁸Ṫ - Link: number, n
Ẇ          - all sublists (implicit range of input) note: ordered by increasing length
           -                i.e. [[1], [2], [3], ..., [1,2], [2,3], ..., [1,2,3], ...]]
 Ḥ         - double              [[2], [4], [6], ..., [2,4], [4,6], ..., [2,4,6], ...]]
  ’        - decrement           [[1], [3], [5], ..., [1,3], [3,5], ..., [1,2,5], ...]]
        ⁸  - link's left argument, n
      Ðḟ   - filter out items for which the following yields a truthy value:
     ¥     -   last two links as a dyad:
   S       -     sum
    _      -     subtract the right from the left = sum - n
         Ṫ - tail (last and hence longest such run)

1
ẆḤ’Speichert ein Byte.
Dennis

8

JavaScript (ES7), 87 86 85 81 Bytes

Gibt eine durch Kommas getrennte Liste von Ganzzahlen zurück oder 0falls keine Lösung vorhanden ist.

n=>(g=(s,k,x=n+s)=>(x**.5|0)**2-x?k>n?0:g(s+k,k+2):(n-=k)?k+','+g(-n,k+2):k)(0,1)

Wie?

Wir suchen zuerst nach dem kleinsten perfekten Quadrat s, so dass x = n + s ein weiteres perfektes Quadrat ist.

Wenn s existiert, ist n die Differenz x - s von 2 perfekten Quadraten, die als Differenz von 2 Folgen aufeinanderfolgender ungerader Zahlen geschrieben werden kann. Wir erstellen dann die resultierende Liste.

Beispiel:

Für n = 104 :

Wir finden s = 11² = 121, was x = n + s = 225 = 15² erfüllt

Dann:

15² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21 + 23 + 25 + 27 + 29
11² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21
104 = 15² - 11² = 23 + 25 + 27 + 29


3
Warten Sie, sagen Sie mir, dass dies n^2immer die Summe der ersten nungeraden Zahlen ist? Huh, interessant
Skidsdev

2
@ Mayube In der Tat !
Arnauld


7

05AB1E , 9 8 Bytes

-1 Byte danke an Emigna

ÅÉŒʒOQ}н

Erläuterung:

ÅÉ           Generate a list of odd numbers up to, and including, the input
  Œ          Substrings
   ʒ         Only keep values
    O          where the sum
     Q         equals the input
       }     End
             For 9, the result would look like this:
             [[1, 3, 5], [9]]
        н    Get the first value

Bei ungültiger Eingabe wird nichts ausgegeben.

Probieren Sie es online!


ʒOQ}statt DO¹QÏspeichert ein Byte.
Emigna

@ JonathanAllan Docs sagen "ungerade", so dass könnte verwirrt gewesen sein ...
Erik der Outgolfer

1
@ JonathanAllan Kleiner Fehler. Fest.
Okx

6

Haskell , 61-60 Bytes

Vielen Dank an @maple_shaft für das Abschneiden von 1 Byte

f n=[k|r<-[1,3..],s<-[r,r+2..n],k<-[[r,r+2..s]],sum k==n]!!0

Probieren Sie es online!

Verwendet die Tatsache, dass der längste Lauf immer der Lauf ist, der mit der niedrigsten Zahl beginnt.

Ich wollte etwas mit Arithmetik machen, anstatt zu brachialisieren k, aber es fromIntegerscheint zu töten.


Sie können sich ein Byte sparen, indem Sie [1,3..n]zu[1,3..]
maple_shaft

1
Sie können 7 Bytes mit einer Hilfsfunktion speichern r?n=[r,r+2..n]. Probieren Sie es online!
Ørjan Johansen

4

Python , 67 Bytes

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

Probieren Sie es online!

Ich kopierte meine Antwort aus der vorherige Mal in Folge Summe Herausforderung und wechselte das +1zu +2. Wer hätte gedacht, dass Golf-Code so modular sein kann?

Eine seltsam einfache Strategie: Suchen Sie nach dem Intervall Rmit der gewünschten Summe.

  • Wenn die Summe zu klein ist, verschieben Sie den rechten Endpunkt des Intervalls um 2, indem Sie die nächste Zahl 2 darüber anhängen.
  • Wenn die Summe zu groß ist, verschieben Sie den linken Endpunkt nach oben, indem Sie das kleinste Element entfernen
  • Wenn die Summe korrekt ist, wird ausgegeben R.

Da das untere Ende des Intervalls nur zunimmt, werden längere Intervalle vor kürzeren gefunden. Wenn kein mögliches Intervall gefunden werden kann, wird mit IndexError abgebrochen.


4

JavaScript (ES6), 65 64 Byte

f=(a,i=1)=>a>i?(c=f(a-i,i+=2))[0]==i?[i-2,...c]:f(a,i):a<i?0:[i]

Gibt ein Array zurück, wenn es eine Lösung gibt, oder 0 für keine Lösung.

Dies ist eine äußerst ineffiziente und dennoch golferische Lösung des Problems.

Es sucht nach der ersten Lösung mit a-iund i=1, auch wenn es die rekursive Stapel nicht aufzuarbeiten. Beginnt diese Lösung nicht mit i+2, suchen wir rekursiv mit aund nach der ersten Lösung i+2.

Ungolfed

f=(a,i=1)=>
  a > i ? 
    (c = f(a - i, i += 2))[0] == i ? 
      [i-2, ...c] : 
      f(a, i) :
  a < i ? 
    0 :
    [i]

Testfälle:

Für eine Vorstellung davon, wie ineffizient dies ist, f(104)erfordert die Lösung 69.535 rekursive Aufrufe. Der Stapel ist nie tiefer als 51 Ebenen, daher kein Problem mit dem Stapelüberlauf.

Die Lösung f(200)erfordert 8,6 Millionen rekursive Aufrufe mit einem Stack von 99 Ebenen. (Seine Lösung ist [11,13,15,17,19,21,23,25,27,29].)

Hier ist eine visuelle Darstellung des laufenden Programms:


3

Python 2.7, 109 108 97 Bytes

11 Bytes weniger, danke an Erik den Outgolfer.

Dies ist mein erster Code Golf!

def f(N):
 for n in range(N):
    x=(n*n+N)**.5-n
    if x%1==0:return[2*(k+n)+1for k in range(int(x))]

Wie es funktioniert

Ich habe die bekannte Identität benutzt 1 + 3 + 5 + ... + (2n - 1) = n²

Nehmen Sie den Fall von 15

15 = 3 + 5 + 7 = (1 + 2) + (3 + 2) + (5 + 2) = (1 + 3 + 5) + 3×2 = 3² + 3×2

Im Allgemeinen, wenn es x Begriffe gibt 2n + 1, die mit wie beginnen

(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))


Es ist gleich 2nx + x²

Wenn Nes sich um die Eingabe-Ganzzahl handelt, wird das Problem auf das Finden des Maximums reduziert, xsodass

x² + 2nx - N = 0

Es ist eine quadratische Gleichung mit Lösung

x = sqrt(n² + N) - n

Die längste Sequenz ist eine mit der größten x. Das Programm iteriert nvon 0bis, Nund wenn es feststellt, dass es sich um xeine Ganzzahl handelt, erstellt es eine Liste von (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))und gibt sie zurück.



@EriktheOutgolfer, Danke, ich habe vergessen, Tabs zu verwenden (=
dark32

3

Python 3, 190 81 Bytes

def c(q,l,i):
    if sum(l)0:
        l.append(i)
        return c(q,l,i+2)
    elif sum(l)>q:
        l.pop(0)
        return c(q,l,i)
    else:
        print(l)
c(q,[1],1)

c=lambda q,l=[1]:c(q,l+[l[-1]+2])if(sum(l)<q)*l else c(q,l[1:])if sum(l)>q else l

Vielen Dank an @ovs und @ musicman523


4
Sie können dies auf 122 Bytes reduzieren, indem Sie nur einige Einrückungen entfernen . Wenn Sie Ihren Code weiter verkürzen möchten, werfen Sie einen Blick auf Tipps zum Golfen in Python .
OVS

3
Dies wird in Python 3 nicht ausgeführt, da beim Aufruf von printKlammern fehlen
musicman523

2
Sie können entfernen, l.append(i)indem Sie einfach l+[i]in dem rekursiven Aufruf verwenden. Sie können entfernen, l.pop(0)indem Sie l[1:]in dem rekursiven Aufruf verwenden. Sie können den Aufruf von cganz unten entfernen, indem Sie stattdessen Schlüsselwortargumente verwenden. Sie können >0in Zeile 2 entfernen . Schließlich können Sie Ihre ifund else-Anweisungen in Ausdrücke umwandeln, indem Sie die ternäre Form verwenden, die Sie als Lambda-Ausdruck auf 92 Byte reduziert. Probieren Sie es online!
musicman523

1
Basierend auf @ musicman523-Vorschlägen können wir die Bedingungen noch verkürzen und iauf insgesamt 81 Bytes reduzieren .
OVS

Ich denke , man könnte sich ändern , sum(l)>q elseum q<sum(l)else1 Byte zu speichern.
Zacharý

2

QBIC , 47 Bytes

{_Cg=q┘q=q+2~g>:|_Xp\?g,[q,a,2|?b,┘g=g+b~g=a|_X

Dies versucht, alle ungeraden Zahlen von eins bis zu ihrer Summe zu zählen n. Wenn es erfolgreich ist n, setzen Sie die Schleife zurück, erhöhen Sie 1 auf 3 und versuchen Sie es erneut. Beenden Sie und geben Sie 0 aus, wenn am Anfang der Schleife unsere Nummer steht > n.

Erläuterung

{       Do infinitely
_C      Clear the screen (we basically print every run of odd numbers, but clear out everything that doesn't sum up to n)
g=q     Set g to the first num of this cycle (q starts as 1 in QBIC)    
┘       (Syntatcic linebreak)
q=q+2   Raise q to the next odd number, this sets up both the next outer loop as well as a coming FOR loop
~g>:|   If we start out with a number > n (read as 'a' from the cmd line)
_Xp     THEN quit, printing 0 (the value of the number var 'p')
\       ELSE
[q,a,2| FOR b = q, b <= n, b+=2
?b,┘    PRINT b followed by a tab
g=g+b   Add 'b' to running total 'g'
~g=a|   and if that lands us on 'n'
_X      QUIT (printing nothing: everything is already printed)

1

R , 90 Bytes

f=function(x,y=1)'if'(length(w<-which(cumsum(r<-y:x*2-1)==x)),r[1:w],'if'(y>x,0,f(x,y+1)))

Probieren Sie es online!

Verwendet eine rekursive Funktion, mit der die kumulative Summe von y: x einer Sequenz mit ungeraden Zahlen getestet wird. y wird bei jeder Rekursion erhöht, bis x überschritten wird. Die erste Sequenz, die dem Ziel entspricht, wird zurückgegeben.


1

Python 2 , 89 Bytes

lambda n,r=range:[v for v in[r(1,n+1,2)[i:j]for i in r(n)for j in r(n+1)]if sum(v)==n][0]

Eine unbenannte Funktion, die eine positive Ganzzahl verwendet nund das Ergebnis zurückgibt, falls es existiert, und eine IndexErrorandere auslöst.

Probieren Sie es online!

Erstellt eine Liste aller relevanten ungeraden Zahlen, mit r(1,n+1,2)denen ist range(start=1, stop=n+1, step=2); erstellt alle relevanten Sub-Slices (plus einige leere), indem sie diese von iinklusive zu jexklusiv mit [i:j]across iin [0, n) mit r(n)und jin [0, n] mit r(n+1)(die leeren, wenn i>=joder iaußerhalb der Grenzen) aufteilen; Filter für diejenigen mit der richtigen Summe mit if sum(v)==n; gibt den ersten (und damit längsten) solchen Slice mit zurück [0].






0

Python 3 , 93 Bytes

lambda n,r=range:[[*r(s,e+1,2)]for s in r(1,n+1,2)for e in r(s,n+1,2)if(s+e)*(2+e-s)==4*n][0]

Probieren Sie es online!

Ich habe nur festgestellt, dass dies (s+e)*(2+e-s)==4*näquivalent ist sum(range(s,e+1,2))==n, und obwohl sie die gleiche Größe haben r=range, kann ersteres näher an die ifAussage herangeführt werden.


0

Python 3 , 185 Bytes

def f(s):
  d={k:v for k,v in{a:(1-a+((a-1)**2+4*s)**(.5))/2 for a in range(1,s,2)}.items()if int(v)==v};m=max(d.keys(), key=(lambda k: d[k]));return list(range(int(m),int(m+2*d[m]),2))

Probieren Sie es online!


Was die Funktionsweise betrifft, habe ich versucht, eine etwas elegantere Lösung als eine einfache Brute-Force-Suche zu finden. Ich habe die Formel für die Summe einer arithmetischen Folge neu angeordnet und die quadratische Formel angewendet, um den Ausdruck zu erhalten (1-a+((a-1)**2+4*s)**(.5))/2, der im Code erscheint. Was der Ausdruck berechnet, ist bei gegebener gewünschter Summe sund einem ersten Term für die arithmetische Folge adie Länge der Folge. Diese Längen werden in einem Wörterbuch als Werte zu den ersten Begriffen als Schlüssel gespeichert.

Als Nächstes werden alle nicht ganzzahligen Werte aus dem Wörterbuch entfernt, da diese ungültige Sequenzen darstellen. Von dort wird der größte Wert mit identifiziert max(d.keys(), key=(lambda k: d[k]))und die Folge von ungeraden Zahlen an dieser Position und in dieser Länge mit erstellt list(range(int(m),int(m+2*d[m]),2)).


Ich suche Hilfe beim Golfen, wenn Sie etwas sehen. Ich war mehr daran interessiert zu sehen, wie gut ich mit einem nicht trivialen Algorithmus umgehen kann. Meine Antwort ist fast doppelt so lang wie die beste Python-Lösung.


Würde das funktionieren? repl.it/JTt7 (177 Bytes)
Zacharý

0

Mathematica, 56 Bytes

Last@Cases[Subsequences@Table[n,{n,1,#,2}],x_/;Tr@x==#]&

Functionmit erstem argument #. Table[n,{n,1,#,2}]berechnet die Liste der positiven ungeraden Zahlen kleiner oder gleich #. SubsequencesGibt alle Untersequenzen dieser Liste in aufsteigender Reihenfolge zurück. Wir nehmen dann die Caseswelche Übereinstimmung x_/;Tr@x==#, das heißt Sequenzen, xso dass ihre Summe Tr@xgleich der Eingabe ist #. Wir nehmen dann die Lastsolche Reihenfolge.


0

JavaScript (ES6), 72 Byte

n=>(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?l+' '+g(s,l+=2):u)(n-1,l=u=1)

Gibt eine durch Leerzeichen getrennte Folge von ungeraden Zahlen zurück oder wirft bei ungültiger Eingabe. 84-Byte-Version, die ein (bei Bedarf leeres) Array zurückgibt:

n=>n%4-2?(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?[l,...g(s,l+=2)]:[u])(n-1,l=u=1):[]

Erläuterung: Basiert lose auf der awk-Lösung von @ Cabbie407 für Summen aufeinanderfolgender Ganzzahlen, außer dass ich mithilfe von Rekursion einige Bytes speichern konnte.


0

PHP, 78 Bytes

for($b=-1;$s-$argn;)for($n=[$s=$x=$b+=2];$s<$argn;)$s+=$n[]=$x+=2;print_r($n);

Endlosschleife, wenn keine Lösung. ?$b>$argn+2?$n=[]:1:0Nach einfügen $s-$argn, um stattdessen ein leeres Array zu drucken.

Laufen Sie mit -nRoder versuchen Sie es online .


0

C # (.NET Core) , 129 Byte

(i)=>{int s,j,b=1,e=3;for(;;){var o="";s=0;for(j=b;j<e;j+=2){s+=j;o+=j+" ";}if(s==i)return o;s=s<i?e+=2:b+=2;if(b==e)return"";}};

Gibt Zahlen in einer Zeichenfolge mit Leerzeichen aus (für jedes andere Zeichen muss nur das Zeichen geändert werden " "). Bei Eingabe ohne Lösung wird eine leere Zeichenfolge zurückgegeben (wenn die Ausführung für immer ohne Fehler eine gültige Methode ist, um anzugeben, dass keine Lösung vorhanden ist, können durch Entfernen 17 Byte gespeichert werden if(b==e)return"";).

Algorithmus ist:

  1. Beginnen Sie mit [1]
  2. Wenn die Summe dem Ziel entspricht, geben Sie die Liste zurück
  3. Wenn die Summe kleiner als das Ziel ist, addieren Sie die nächste ungerade Zahl
  4. Wenn die Summe größer als das Ziel ist, entfernen Sie das erste Element
  5. Wenn die Liste leer ist, geben Sie sie zurück
  6. Wiederholen Sie ab 2

Sie können schreiben, (i)=>wiei=>
aloisdg sagt Reinstate Monica

0

C ++, 157 -> 147 Bytes


-10 Bytes dank DJMcMayhem

Gibt 0 zurück, wenn keine Antwort erfolgt, andernfalls 1

Die letzte Zeile, die gedruckt wird, ist die Antwort

int f(int n){for(int i=1;;i+=2){int v=0;for(int k=i;;k+=2){v+=k;std::cout<<k<<" ";if(v==n)return 1;if(v>n)break;}if(i>n)return 0;std::cout<<"\n";}}

ungolfed:

int f(int n)
{
    for (int i = 1;; i += 2)
    {
        int v = 0;
        for (int k = i;; k += 2)
        {
            v += k;
            std::cout << k << " ";
            if (v == n)
                return 1;
            if (v > n)
                break;

        }
        if (i > n)
            return 0;
        std::cout << "\n";
    }
}

Das ist mein erster Code Golf ^^


Sie könnten einige Bytes einsparen, wenn Sie es zu einer int-Funktion machen und 0 oder 1 zurückgeben. Sie könnten auch tun, int v=0;anstatt int v;....v=0;und wenn Sie Ihre Ausgabe Newline-getrennt machen, könnten Sie std::cout<<k<<"\n";die zweite Newline insgesamt machen und dann entfernen
DJMcMayhem

Wenn ich die letzte Empfehlung gemacht hätte, würde es eine neue Zeile auf jede einzelne Nummer drucken, aber ich möchte Nummerngruppen trennen, aber trotzdem danke für -10 Bytes
SeeSoftware

0

Kotlin, 152 Bytes

fun f(a:Double){var n=Math.sqrt(a).toInt()+1;var x=0;while(n-->0){if(((a/n)-n)%2==0.0){x=((a/n)-n).toInt()+1;while(n-->0){println(x.toString());x+=2}}}}

Probieren Sie es online aus (Warten Sie 4-5 Sekunden, der Compiler ist langsam)

Ungolfed

fun f(a: Double){
    var n=Math.sqrt(a).toInt()+1;
    var x=0;

    while(n-->0){
        if(((a/n)-n)%2==0.0){
            x=((a/n)-n).toInt()+1;

            while(n-->0){
                println(x.toString());
                x+=2;
            }

        }
    }
}

0

Excel VBA, 139 Bytes

SubRoutine, die die Eingabe neiner Ganzzahl des erwarteten Typs annimmt und die längste Folge von ungeraden Folgenummern an die Zelle meldet[A1]

Sub a(n)
For i=1To n Step 2
s=0
For j=i To n Step 2
s=s+j
If s=n Then:For k=i To j-1 Step 2:r=r &k &"+":Next:[A1]=r &j:End
Next j,i
End Sub
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.