La suma de números impares consecutivos.

24

Aunque se han planteado desafíos relacionados , este es diferente para justificar su propia pregunta.


Reto

Dado un entero positivo, devuelve la secuencia más larga de enteros impares consecutivos positivos cuya suma es el entero dado. Si no existe tal secuencia, puede informar un error de cualquier manera que tenga sentido para su idioma, incluyendo devolver un valor falso o lanzar una excepción.

Casos de prueba

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (tenga en cuenta que [9] no es una respuesta válida)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (tenga en cuenta que [51, 53] no es una respuesta válida)

Tanteo

Este es el , por lo que gana la respuesta más corta en cada idioma.

musicman523
fuente
2
¿Puede mi programa ejecutarse para siempre si no hay solución?
Dennis
Muy relacionado . Sin embargo, el hecho de que algunos números pares no se puedan representar en este podría salvarlo de ser un engañado.
ETHproductions
66
¿No pueden 15 dar [-1, 1, 3, 5, 7]? Si solo se permiten valores positivos, debe decirlo.
xnor
2
@ ЕвгенийНовиков te saltaste el 17
kalsowerus
1
@kalsowerus sí. No entiendo la palabra "consecutiva"
Евгений Новиков

Respuestas:

11

Haskell, 67 65 63 62 58 bytes

Guardado 4 bytes gracias 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

Pruébalo en línea!

Puedo comprobar si el número se puede expresar como la diferencia de dos cuadrados: m^2-n^2. Entonces puede construir la lista de números impares consecutivos: [2n+1,2n+3...2m-1]. Tenga en cuenta que debido a que nse elige el mínimo , se generará la lista más larga

H.PWiz
fuente
77
Votante: sería a la vez más amable y constructivo agregar un comentario que explique su razón, especialmente al votar a favor de un nuevo usuario.
Jonathan Allan
1
A menos que me falte algo, puede guardar 4 bytes solo xpara ambos nym
Julian Wolf
Para que lo sepas, el usuario de la comunidad emitió automáticamente el voto negativo cuando editaste tu respuesta. Considero que esto es un error . (CC @JonathanAllan)
Dennis
Ahh, fue uno de esos.
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

Sale con un RuntimeError (profundidad de recursión máxima excedida) si no hay solución.

Pruébalo en línea!

Dennis
fuente
1
Si los valores de entrada son lo suficientemente altos, pero hay una solución, ¿esto resultará en un RuntimeError ?
Okx
Si el límite de recursión no es lo suficientemente alto y / o la pila no es lo suficientemente grande, sí. Sin embargo, es común ignorar las limitaciones físicas (por ejemplo, una respuesta C solo tiene que funcionar para entradas de 32 bits), y el OP dijo explícitamente que correr para siempre es aceptable si no hay solución.
Dennis
9

Jalea ,  11  10 bytes

-1 byte gracias a Dennis (use la construcción de rango implícita de - reemplace Rm2Ẇcon ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Un enlace monádico que devuelve una lista de los sumandos si es posible, o 0si no.

Pruébalo en línea!

¿Cómo?

ẆḤ’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)
Jonathan Allan
fuente
1
ẆḤ’Guarda un byte.
Dennis
8

JavaScript (ES7), 87 86 85 81 bytes

Devuelve una lista de enteros delimitada por comas, o 0si no existe una solución.

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)

¿Cómo?

Primero buscamos el cuadrado perfecto más pequeño s de modo que x = n + s sea ​​otro cuadrado perfecto.

Si s existe, n es la diferencia x - s de 2 cuadrados perfectos, que puede escribirse como la diferencia de 2 secuencias de números impares consecutivos. Luego construimos la lista resultante.

Ejemplo:

Para n = 104 :

Encontramos s = 11² = 121 que satisface x = n + s = 225 = 15²

Luego:

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 +
21104 = 15² - 11² = 23 + 25 + 27 + 29

Arnauld
fuente
3
Espera, ¿me estás diciendo que n^2siempre es igual a la suma de los primeros nnúmeros impares? Huh, interesante
Skidsdev
2
@Mayube De hecho !
Arnauld
7

05AB1E , 9 8 bytes

-1 byte gracias a Emigna

ÅÉŒʒOQ}н

Explicación:

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

En una entrada no válida, no genera nada.

Pruébalo en línea!

Okx
fuente
ʒOQ}en lugar de DO¹QÏguardar un byte.
Emigna
@JonathanAllan Docs dice "desigual", por lo que podría haberse confundido ...
Erik the Outgolfer
1
@JonathanAllan Pequeño error. Fijo.
Okx
6

Haskell , 61 60 bytes

Gracias a @maple_shaft por eliminar 1 byte

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

Pruébalo en línea!

Utiliza el hecho de que la ejecución más larga siempre será la que comienza con el número más bajo.

Quería hacer algo con aritmética en lugar de fuerza bruta k, pero fromIntegerparece matarlo.

Julian Wolf
fuente
Puede ahorrarse un byte cambiando [1,3..n]a[1,3..]
maple_shaft
1
Puede guardar 7 bytes con una función auxiliar r?n=[r,r+2..n]. Pruébalo en línea!
Ø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

Pruébalo en línea!

Copié mi respuesta del desafío de suma consecutiva anterior y cambié +1a +2. ¿Quién sabía que el código de golf podría ser tan modular?

Una estrategia extrañamente sencilla: busca el intervalo Rcon la suma deseada.

  • Si la suma es demasiado pequeña, cambie el punto final derecho del intervalo hacia arriba 2 agregando el siguiente número 2 arriba.
  • Si la suma es demasiado grande, suba el punto final izquierdo eliminando el elemento más pequeño
  • Si la suma es correcta, salida R.

Como el extremo inferior del intervalo solo aumenta, se encuentran intervalos más largos antes que los más cortos. Si no se puede encontrar un intervalo posible, termina con IndexError.

xnor
fuente
4

JavaScript (ES6), 65 64 bytes

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

Devuelve una matriz si hay una solución, o 0 para ninguna solución.

Este es un campo de golf altamente ineficiente pero solución al problema.

Busca la primera solución usando a-ie i=1, incluso si no funciona en la pila recursiva. Si esa solución no comienza i+2, entonces buscamos recursivamente la primera solución usando ay i+2.

Sin golf

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

Casos de prueba:

Para tener una idea de cuán ineficiente es esto, la solución f(104)requiere 69.535 llamadas recursivas. La pila nunca tiene más de 51 niveles de profundidad, por lo que no hay problema con el desbordamiento de la pila.

La solución f(200)requiere 8,6 millones de llamadas recursivas, con una pila de 99 niveles de profundidad. (Su solución es [11,13,15,17,19,21,23,25,27,29]).

Aquí hay una representación visual del programa en ejecución:

Rick Hitchcock
fuente
3

Python 2.7, 109 108 97 bytes

11 bytes hacia abajo, gracias a Erik the Outgolfer.

Este es mi primer código de 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))]

Cómo funciona

Usé la conocida identidad que 1 + 3 + 5 + ... + (2n - 1) = n²

Toma el caso de 15

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

En general, si hay x términos a partir de 2n + 1, como

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


Es igual a 2nx + x²

Si Nes el entero de entrada, el problema se reduce a encontrar el máximo xtal que

x² + 2nx - N = 0

Es una ecuación cuadrática con solución.

x = sqrt(n² + N) - n

La secuencia más larga es una con la más grande x. El programa itera na partir 0de Ny cuando se encuentra que xes un número entero, se crea una lista de (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))y lo devuelve.

dark32
fuente
@EriktheOutgolfer, gracias, olvidé usar pestañas (=
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

Gracias a @ovs y @ musicman523

Simon
fuente
44
Puede reducir esto a 122 bytes simplemente quitando alguna sangría . Si desea acortar aún más su código, eche un vistazo a Consejos para jugar golf en Python .
ovs
3
Esto no se ejecuta en Python 3, porque la llamada a printfalta paréntesis
musicman523
2
Puede eliminar l.append(i)simplemente usando l+[i]en la llamada recursiva. Puede eliminar l.pop(0)mediante el uso l[1:]de la llamada recursiva. Puede eliminar la llamada cen la parte inferior utilizando argumentos de palabras clave en su lugar. Puede eliminar >0en la línea 2. Finalmente, puede cambiar sus declaraciones ify elseen expresiones, utilizando la forma ternaria, que lo lleva a 92 bytes como una expresión lambda. Pruébalo en línea!
musicman523
1
Según las sugerencias de @ musicman523, aún podemos acortar las condiciones y soltar ihasta llegar a un total de 81 bytes .
ovs
Creo que se podría cambiar sum(l)>q elsea q<sum(l)elseahorrar 1 byte.
Zacharý
2

QBIC , 47 bytes

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

Esto intenta contar todos los números impares de uno hasta que su suma sea n. Si pasa n, reinicie el ciclo, aumente de 1 a 3 e intente nuevamente. Salga, imprimiendo 0, si al comienzo del ciclo nuestro número > n.

Explicación

{       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)
Steenbergh
fuente
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)))

Pruébalo en línea!

Utiliza una función recursiva que prueba la suma acumulativa de la secuencia de y: x convertida en una secuencia de números impares. y se incrementa en cada recursión hasta que excede x. Se devolverá la primera secuencia que suma al objetivo.

MickyT
fuente
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]

Una función sin nombre que toma un número entero positivo n, y devuelve el resultado si existe y genera un resultado diferente IndexError.

Pruébalo en línea!

Crea una lista de todos los números impares relevantes con los r(1,n+1,2)que está range(start=1, stop=n+1, step=2); crea todos los sub-cortes relevantes (más algunos vacíos) al dividir eso de iinclusivo a jexclusivo con [i:j]across ien [0, n) usando r(n)y jen [0, n] usando r(n+1)(los vacíos cuando i>=jo iestá fuera de los límites); filtros para aquellos con la suma correcta con if sum(v)==n; devuelve el primer segmento (y, por lo tanto, el más largo) usando [0].

Jonathan Allan
fuente
1

Python 2 , 91 90 bytes

-1 byte gracias 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]

Pruébalo en línea!

ovs
fuente
1

PHP , 73 bytes

ninguna solución es un bucle infinito

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

Pruébalo en línea!

PHP , 83 bytes

no imprime nada sin solución

cada mod de entrada 4 == 2 no tiene solución

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

Pruébalo en línea!

Jörg Hülsermann
fuente
no detecta la entrada insoluble
Titus
@Titus arreglado ...
Jörg Hülsermann
0

Python 2 , 122 121 119 115 bytes

-1 byte gracias a musicman523. -4 bytes gracias a Step Hen. jaja

def f(n,R=range):r=R(1,n,2);print[i for w in R(1,len(r)+1)for i in[r[j:j+w]for j in R(len(r)-w+1)]if sum(i)==n][-1]

Pruébalo en línea!

totalmente humano
fuente
1
Este es un byte más corto como una función. Pruébalo en línea!
musicman523
Ahorre bytes si redefine range, ¡ Pruébelo en línea!
Stephen
Esto falla para 1 .
Dennis
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]

Pruébalo en línea!

Lo único que hice fue notar que (s+e)*(2+e-s)==4*nes equivalente a sum(range(s,e+1,2))==n, y aunque son del mismo tamaño cuando r=range, el primero se puede colocar más cerca de la ifdeclaración.

C McAvoy
fuente
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))

Pruébalo en línea!


En cuanto a cómo funciona esto, traté de buscar una solución un poco más elegante que una simple búsqueda de fuerza bruta. Reorganicé la fórmula para la suma de una secuencia aritmética y apliqué la fórmula cuadrática para obtener la expresión (1-a+((a-1)**2+4*s)**(.5))/2, que aparece en el código. Lo que calcula la expresión es, dada una suma deseada sy un primer término para secuencia aritméticaa , la longitud de la secuencia. Estas longitudes se almacenan en un diccionario como valores para los primeros términos como claves.

A continuación, todos los valores no enteros se eliminan del diccionario, ya que representan secuencias no válidas. A partir de ahí, se identifica el valor más grande max(d.keys(), key=(lambda k: d[k]))y con la secuencia de números impares en esa posición y en esa longitud list(range(int(m),int(m+2*d[m]),2)).


Estoy buscando ayuda para jugar golf si ves algo. Estaba más interesado en ver qué tan bien podía hacerlo con un algoritmo no trivial; mi respuesta es casi el doble que la mejor solución de Python.

Chase Vogeli
fuente
¿Funcionaría esto? repl.it/JTt7 (177 bytes)
Zacharý
0

Mathematica, 56 bytes

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

Functioncon el primer argumento #. Table[n,{n,1,#,2}]calcula la lista de números impares positivos menores o iguales que #. Subsequencesdevuelve todas las subsecuencias de esa lista ordenadas al aumentar la longitud. Luego tomamos la secuencia de Casescoincidencias x_/;Tr@x==#, es decir, de xtal manera que su suma Tr@xes igual a la entrada #. Luego tomamos la Lastsecuencia.

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

Devuelve una cadena separada por espacios de números impares o arroja entradas no válidas. Versión de 84 bytes que devuelve una matriz (vacía cuando corresponde):

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

Explicación: Basado libremente en la solución awk de @ Cabbie407 para Sumas de enteros consecutivos, excepto que pude guardar algunos bytes mediante la recursión.

Neil
fuente
0

PHP, 78 bytes

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

bucle infinito si no hay solución. insertar?$b>$argn+2?$n=[]:1:0 después $s-$argnpara imprimir matriz vacía en su lugar.

Ejecutar -nRo probarlo en línea .

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

Emite números en una cadena, espacio delimitado (cualquier otro carácter solo requeriría cambiar el " " ). La entrada sin solución devuelve una cadena vacía (aunque si se ejecuta para siempre sin error es una forma válida de indicar que no hay solución, se podrían guardar 17 bytes eliminandoif(b==e)return""; ).

Algoritmo es:

  1. Comience con [1]
  2. Si la suma es igual al objetivo, devuelva la lista
  3. Si la suma es menor que el objetivo, agregue el siguiente número impar
  4. Si la suma es mayor que el objetivo, elimine el primer elemento
  5. Si la lista está vacía, devuélvala
  6. Repetir desde 2
Kamil Drakari
fuente
Puede escribir (i)=>comoi=>
aloisdg dice Reinstate Monica el
0

C ++, 157 -> 147 bytes


-10 Bytes gracias a DJMcMayhem

devolverá 0 si no hay respuesta, 1 de lo contrario

la última línea que imprime es la respuesta

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

sin golf:

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

este es mi primer código de golf ^^

Ver software
fuente
Podría guardar algunos bytes si lo convirtió en una función int y devolvió 0 o 1. Además, podría hacerlo en int v=0;lugar de int v;....v=0;y si hizo que su línea Newline delimitada, podría hacer std::cout<<k<<"\n";y luego eliminar la segunda línea nueva por completo
DJMcMayhem
si hice la última recomendación, imprimiría una nueva línea en cada número, pero quiero separar los grupos de números, pero gracias de todos modos por -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}}}}

Pruébelo en línea (espere de 4 a 5 segundos, el compilador es lento)

Sin golf

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

        }
    }
}
Евгений Новиков
fuente
0

Excel VBA, 139 bytes

Subrutina que toma la entrada ndel tipo entero esperado e informa la secuencia más larga de números impares consecutivos a la celda[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
Taylor Scott
fuente