La somma dei numeri dispari consecutivi


24

Sebbene siano state poste sfide correlate , questa è diversa per giustificare la propria domanda.


Sfida

Dato un numero intero positivo, restituisce la sequenza più lunga di numeri interi dispari positivi consecutivi la cui somma è il numero intero indicato. Se tale sequenza non esiste, è possibile segnalare un errore in qualsiasi modo abbia senso per la propria lingua, incluso la restituzione di un valore falso o il lancio di un'eccezione.

Casi test

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (nota che [9] non è una risposta valida)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (nota che [51, 53] non è una risposta valida)

punteggio

Questo è , quindi vince la risposta più breve in ogni lingua.


2
Il mio programma può funzionare per sempre se non c'è soluzione?
Dennis,

Molto correlate . Il fatto che alcuni numeri pari non possano essere rappresentati in questo potrebbe salvarlo dall'essere un duplicato.
ETHproductions

6
15 non possono dare [-1, 1, 3, 5, 7]? Se sono ammessi solo valori positivi, dovresti dirlo.
xnor

2
@ ЕвгенийНовиков hai saltato 17
kalsowerus

1
@kalsowerus sì. Ho frainteso la parola "consecutivo"
Евгений Новиков

Risposte:


11

Haskell, 67 65 63 62 58 byte

Salvato 4 byte grazie a Julian Wolf

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

Provalo online!

Posso controllare se il numero può essere espresso come lui differenza di due quadrati: m^2-n^2. Posso quindi costruire l'elenco dei numeri dispari consecutivi: [2n+1,2n+3...2m-1]. Si noti che poiché nviene scelto il minimo , verrà visualizzato l'elenco più lungo


7
Down-voter: sarebbe sia più amichevole che costruttivo aggiungere un commento che fornisca il motivo, in particolare quando si vota in negativo un nuovo utente.
Jonathan Allan,

1
A meno che non mi manchi qualcosa, puoi salvare 4 byte solo andando su xper entrambi nem
Julian Wolf,

Proprio per questo sai, il downvote è stato lanciato automaticamente dall'utente della Community quando hai modificato la tua risposta. Lo considero un bug . (CC @JonathanAllan)
Dennis

Ah, era uno di quelli.
Jonathan Allan,

9

Python 2 , 66 62 byte

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

Esce con un RuntimeError (superata la profondità massima di ricorsione) se non c'è soluzione.

Provalo online!


1
Se i valori di input sono abbastanza alti, ma esiste una soluzione, questo si tradurrà in un RuntimeError ?
Okx,

Se il limite di ricorsione non è abbastanza alto e / o lo stack non è abbastanza grande, sì. Tuttavia, è comune ignorare le limitazioni fisiche (ad esempio, una risposta C deve funzionare solo per ints a 32 bit) e l'OP ha esplicitamente affermato che l'esecuzione per sempre è accettabile se non c'è soluzione.
Dennis,

9

Gelatina ,  11  10 byte

-1 byte grazie a Dennis (usa la costruzione dell'intervallo implicito di - sostituisci Rm2Ẇcon ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Un collegamento monadico che restituisce un elenco dei riepiloghi, se possibile, o in 0caso contrario.

Provalo online!

Come?

ẆḤ’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
ẆḤ’salva un byte.
Dennis,

8

JavaScript (ES7), 87 86 85 81 byte

Restituisce un elenco di numeri interi delimitati da virgole o 0se non esiste una soluzione.

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)

Come?

Abbiamo primo sguardo per il più piccolo quadrato perfetto s tali che x = n + s è un altro quadrato perfetto.

Se s esiste, n è la differenza x - s di 2 quadrati perfetti, che può essere scritta come la differenza di 2 sequenze di numeri dispari consecutivi. Costruiamo quindi l'elenco risultante.

Esempio:

Per n = 104 :

Troviamo s = 11² = 121 che soddisfa x = n + s = 225 = 15²

Poi:

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
Aspetta, mi stai dicendo che n^2è sempre uguale alla somma dei primi nnumeri dispari? Eh, interessante
Skidsdev il

2
@Mayube Indeed !
Arnauld,


7

05AB1E , 9 8 byte

-1 byte grazie a Emigna

ÅÉŒʒOQ}н

Spiegazione:

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

Su input non valido, non genera nulla.

Provalo online!


ʒOQ}invece di DO¹QÏsalvare un byte.
Emigna,

@JonathanAllan Docs dice "irregolare", quindi potrebbe essere stato confuso ...
Erik the Outgolfer

1
@JonathanAllan Piccolo errore. Fisso.
Okx,

6

Haskell , 61 60 byte

Grazie a @maple_shaft per la rasatura di 1 byte

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

Provalo online!

Usa il fatto che la corsa più lunga sarà sempre la corsa che inizia con il numero più basso.

Volevo fare qualcosa con l'aritmetica al posto della forza bruta k, ma fromIntegersembra ucciderlo.


Puoi salvarti un byte cambiando [1,3..n]in[1,3..]
maple_shaft il

1
È possibile salvare 7 byte con una funzione di supporto r?n=[r,r+2..n]. Provalo online!
Ørjan Johansen,

4

Python , 67 byte

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

Provalo online!

Ho copiato la mia risposta dal precedente sfida somma consecutivo e ha cambiato la +1a+2 . Chi sapeva che il codice golf potrebbe essere così modulare?

Una strategia stranamente semplice: cerca l'intervallo Rcon la somma desiderata.

  • Se la somma è troppo piccola, sposta l'endpoint destro dell'intervallo su 2 aggiungendo il numero successivo 2 sopra di esso.
  • Se la somma è troppo grande, sposta verso l'alto l'endpoint sinistro rimuovendo l'elemento più piccolo
  • Se la somma è corretta, emettere R.

Poiché l'estremità inferiore dell'intervallo aumenta solo, vengono trovati intervalli più lunghi prima di quelli più brevi. Se non è possibile trovare alcun intervallo possibile, termina con IndexError.


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]

Restituisce un array se esiste una soluzione o 0 per nessuna soluzione.

Questo è altamente inefficiente ma da golf al problema.

Cerca la prima soluzione usando a-ie i=1, anche se non funziona nello stack ricorsivo. Se quella soluzione non inizia con i+2, ricerchiamo ricorsivamente la prima soluzione usando ae 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]

Casi test:

Per un'idea di quanto sia inefficiente, la soluzione a f(104) richiede 69.535 chiamate ricorsive. Lo stack non è mai profondo più di 51 livelli, quindi nessun problema con lo overflow dello stack.

La soluzione f(200)richiede 8,6 milioni di chiamate ricorsive, con uno stack di 99 livelli di profondità. (La sua soluzione è[11,13,15,17,19,21,23,25,27,29] .)

Ecco una rappresentazione visiva del programma in esecuzione:


3

Python 2.7, 109 108 97 byte

11 byte in meno, grazie a Erik the Outgolfer.

Questo è il mio primo codice 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))]

Come funziona

Ho usato l'identità ben nota che 1 + 3 + 5 + ... + (2n - 1) = n²

Prendi il caso di 15

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

In generale, se ci sono x termini a partire da 2n + 1, come

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


È uguale a 2nx + x²

Se Nè il numero intero di input, il problema si riduce a trovare il massimo xtale

x² + 2nx - N = 0

È un'equazione quadratica con soluzione

x = sqrt(n² + N) - n

La sequenza più lunga è quella con la più grande x. Il programma scorre nda 0a Ne quando trova xun numero intero, crea un elenco di (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))e lo restituisce.



@EriktheOutgolfer, grazie, mi sono dimenticato di usare le schede (=
dark32

3

Python 3, 190 81 byte

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

Grazie a @ovs e @ musicman523


4
È possibile ottenere questo fino a 122 byte semplicemente rimuovendo alcuni rientri . Se vuoi abbreviare ulteriormente il codice, dai un'occhiata a Suggerimenti per giocare a golf in Python .
Ovs,

3
Questo non funziona in Python 3, perché nella chiamata printmancano le parentesi
musicman523

2
È possibile rimuovere l.append(i)semplicemente utilizzando l+[i]nella chiamata ricorsiva. È possibile rimuovere l.pop(0)utilizzando l[1:]nella chiamata ricorsiva. Puoi rimuovere la chiamata cin fondo usando invece argomenti per parole chiave. È possibile rimuovere >0alla riga 2. Infine, è possibile modificare espressioni ife elsein espressioni, utilizzando la forma ternaria, che porta a 92 byte come espressione lambda. Provalo online!
musicman523

1
Sulla base dei suggerimenti di @ musicman523, possiamo ancora abbreviare le condizioni e rilasciarle iper arrivare a un totale di 81 byte .
Ovs,

Penso che potresti cambiare sum(l)>q elsein q<sum(l)elseper salvare 1 byte.
Zacharý,

2

QBIC , 47 byte

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

Questo tenta di contare tutti i numeri dispari da uno fino a quando la sua somma è n. Se passa n, reimposta il loop, aumenta da 1 a 3 e riprova. Esci, stampa 0, se all'inizio del ciclo il nostro numero > n.

Spiegazione

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

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

Provalo online!

Utilizza una funzione ricorsiva che verifica la somma cumulativa della sequenza di y: x convertita in una sequenza di numeri dispari. y viene incrementato ad ogni ricorsione fino a quando non supera x. Verrà restituita la prima sequenza che si somma al bersaglio.


1

Python 2 , 89 byte

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]

Una funzione senza nome che prende un numero intero positivo ne restituisce il risultato se esiste e genera un IndexErroraltro.

Provalo online!

Crea un elenco di tutti i numeri dispari rilevanti con r(1,n+1,2)cui è range(start=1, stop=n+1, step=2); crea tutti i sottotitoli rilevanti (più alcuni vuoti) tagliando da iinclusivo a jesclusivo con [i:j]across iin [0, n) using r(n)e jin [0, n] using r(n+1)(quelli vuoti quando i>=jo iè fuori dai limiti); filtri per quelli con la somma corretta con if sum(v)==n; restituisce il primo (e quindi il più lungo) tale slice usando [0].


1

Python 2 , 91 90 byte

-1 byte grazie a @CMcAvoy

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

Provalo online!



1

PHP, 73 bytes

no solution is a infinite loop

for($e=-1;$s-$i=$argn;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Try it online!

PHP, 83 bytes

prints nothing for no solution

every input mod 4 == 2 has no solution

for($e=-1;($i=$argn)%4-2&&$s-$i;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Try it online!


fails to detect unsolvable input
Titus

@Titus fixed...
Jörg Hülsermann


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]

Try it online!

Only thing special I did was noting that (s+e)*(2+e-s)==4*n is equivalent to sum(range(s,e+1,2))==n, and though they're the same size when r=range, the former can be placed closer to the if statement.


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

Try it online!


As for how this works, I tried to go for a bit more elegant solution than a simple brute force search. I rearranged the formula for the sum of an arithmetic sequence and applied the quadratic formula to get the expression (1-a+((a-1)**2+4*s)**(.5))/2, which appears in the code. What the expression calculates is, given a desired sum s and a first term for of arithmetic sequence a, the length of the sequence. These lengths are stored in a dictionary as values to the first terms as keys.

Next, all non-integer values are removed from the dictionary, as those represent invalid sequences. From there, the largest value is identified with max(d.keys(), key=(lambda k: d[k])) and the sequence of odd numbers at that position and at that length is made with list(range(int(m),int(m+2*d[m]),2)).


I'm looking for help golfing this if you see anything. I was more interested in seeing how well I could do with a non-trivial algorithm; my answer is nearly twice as long as the best Python solution.


Would this work? repl.it/JTt7 (177 bytes)
Zacharý

0

Mathematica, 56 bytes

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

Function with first argument #. Table[n,{n,1,#,2}] computes the list of positive odd numbers less than or equal to #. Subsequences returns all subsequences of that list ordered by increasing length. We then take the Cases which match x_/;Tr@x==#, that is, sequences x such that their sum Tr@x is equal to the input #. We then take the Last such sequence.


0

JavaScript (ES6), 72 bytes

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)

Returns a space-separated string of odd numbers or throws on invalid input. 84 byte version that returns an (empty when appropriate) array:

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):[]

Explanation: Loosely based on @Cabbie407's awk solution to Sums of Consecutive Integers except I was able to save some bytes by using recursion.


0

PHP, 78 bytes

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

infinite loop if no solution. insert ?$b>$argn+2?$n=[]:1:0 after $s-$argn to print empty array instead.

Run with -nR or try it online.


0

C# (.NET Core), 129 bytes

(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"";}};

Outputs numbers in a string, space delimited (any other character would just require changing the " "). Input with no solution returns an empty string (though if running forever without error is a valid way to indicate no solution then 17 bytes could be saved by removing if(b==e)return"";).

Algorithm is:

  1. Start with [1]
  2. If the sum is equal to the target, return the list
  3. If the sum is less than the target, add the next odd number
  4. If the sum is greater than the target, remove the first item
  5. If the list is empty, return it
  6. Repeat from 2

You can write (i)=> as i=>
aloisdg says Reinstate Monica

0

C++, 157 -> 147 Bytes


-10 Bytes thanks to DJMcMayhem

will return 0 if there's no answer, 1 otherwise

the last line it prints is the answer

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";
    }
}

this is my first code golf ^^


You could save some bytes if you made it an int function and returned 0 or 1. Also, you could do int v=0; instead of int v;....v=0; and if you made your output Newline delimited, you could do std::cout<<k<<"\n"; and then remove the second Newline altogether
DJMcMayhem

the if i did the last recomendation then it would print a new line on every single number but i want to seperate number groups, but thanks anyways for -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}}}}

Try it online (Wait 4-5 seconds, compiler is slow)

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 that takes input n of expected type integer and reports the longest sequence of consecutive odd numbers to cell [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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.