Mathematica, 79 bytes
Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&
Explicación
No podía molestarme en implementar el algoritmo en el desafío, por lo que quería buscar un acceso directo a la solución. Si bien encontré uno, desafortunadamente no supera la respuesta de Mathematica que implementa el algoritmo. Dicho esto, estoy seguro de que esto aún no está optimizado, y puede haber otros idiomas que puedan beneficiarse de este enfoque o de algunas de las ideas obtenidas en el proceso.
Entonces afirmo que la secuencia que se supone que debemos calcular es:
f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)
Alternativamente, es f (n) = 1 si n es un número triangular yf (n) = 2 * ( A212652 (n) - A002024 (n) + 1) de lo contrario.
En la primera expresión, A023532 simplemente codifica estos dos casos diferentes. Las otras dos secuencias (más 1) son la diferencia entre el el mayor entero k en la descomposición más larga de n en enteros consecutivos (k-i + 1) + (k-i + 2) + ... + k = n y el entero más grande j para que 1 + 2 + ... + j <n .
En palabras algo más simples, así es como encontramos la respuesta para números no triangulares: primero, encuentre el número triangular más grande T j que sea menor que n . Entonces j es el penúltimo entero que se agrega durante el paso 1 (porque después de agregar j + 1 habremos excedido n ). Luego descomponga n en tantos (o tan pequeños) enteros consecutivos como sea posible y llame al máximo entre estos números k . El resultado es simplemente 2 * (kj) . La razón intuitiva para esto es que el máximo en la descomposición crece en 1 cada dos pasos y nos detenemos cuando alcanzamosk .
Necesitamos mostrar cuatro cosas para demostrar que esto funciona:
- f (n) = 1 para números triangulares. Este es trivial el caso, porque el primer paso simplemente itera a través de todos los números triangulares. Si tocamos n exactamente durante este proceso, hemos terminado y solo había un paso para calcular.
- Para todos los demás números, siempre terminamos después de un paso de eliminación, nunca después de un paso de inserción. Eso significa que todos los demás f (n) son pares.
- En cada paso de inserción después del primero, solo agregamos un solo número. Esto garantiza que alcanzaremos una descomposición que incluye k después de kj pares de pasos.
- La descomposición final de n que obtenemos es siempre la descomposición más larga posible de n en enteros consecutivos, o en otras palabras, siempre es la descomposición de n con el máximo más bajo entre los números sumados. En otras palabras, el último número que agregamos a la suma es siempre A212652 (n) .
Ya hemos demostrado por qué (1) es cierto. A continuación, demostramos que no podemos terminar en un paso de inserción excepto el inicial (que no ocurre con números no triangulares).
Supongamos que terminamos en un paso de inserción, alcanzando n después de agregar un valor p a la suma. Eso significa que antes de este paso de inserción, el valor era np ( o menos si agregamos múltiples valores a la vez). Pero este paso de inserción fue precedido por un paso de eliminación (ya que no podríamos haber presionado n durante el paso 1). El último valor q que eliminamos durante este paso de eliminación fue necesariamente menor que p debido a la forma en que funciona el algoritmo. Pero eso significa que antes de eliminar q teníamos n-p + q ( o menos ) que es menor que n. Pero eso es una contradicción, porque habríamos tenido que dejar de eliminar enteros cuando golpeamos n-p + q en lugar de eliminar otro q . Esto prueba el punto (2) anterior. Así que ahora sabemos que siempre terminamos en un paso de eliminación y que, por lo tanto, todos los números no triangulares tienen salidas pares.
A continuación, demostramos (3) que cada paso de inserción solo puede insertar un valor. Esto es esencialmente un corolario de (2). Hemos demostrado que después de agregar un valor no podemos golpear n exactamente y dado que la prueba estaba usando una desigualdad, tampoco podemos terminar debajo de n (ya que entonces n-p + q aún sería menor que n y no deberíamos haber eliminado que muchos valores en primer lugar). Entonces, cada vez que agreguemos un valor único, se nos garantiza que excedemos n porque bajamos de n eliminando un valor más pequeño. Por lo tanto, sabemos que el extremo superior de la suma crece en 1 cada dos pasos. Conocemos el valor inicial de este extremo superior (es el m más pequeño tal queT m > n ). Ahora solo tenemos que descubrir este extremo superior una vez que hayamos alcanzado la suma final. Entonces el número de pasos es simplemente el doble de la diferencia (más 1).
Para hacer esto, demostramos (4), que la suma final es siempre la descomposición de n en tantos números enteros como sea posible, o la descomposición donde el máximo en esa descomposición es mínimo (es decir, es la descomposición más temprana posible). Nuevamente haremos esto por contradicción (la redacción en esta parte podría ser un poco más rigurosa, pero ya he pasado demasiado tiempo en esto ...).
Digamos que la descomposición más temprana / más larga posible de n es alguna a + (a + 1) + ... (b-1) + b , a ≤ b , y digamos que el algoritmo lo omite. Eso significa que en el momento en que se agrega b , a ya no debe ser parte de la suma. Si a fuera parte de la suma s , entonces tendríamos n ≤ s en ese momento. Entonces, o la suma solo contiene los valores de a a b , que es igual a ny nos detenemos (por lo tanto, no omitimos esta descomposición), o hay al menos un valor menor que a en la suma, gana en cuyo caso n <sy ese valor se eliminaría hasta llegar a la suma exacta (nuevamente, no se omitió la descomposición). Entonces tendríamos que deshacernos de a antes de agregar b . Pero eso significa que tendríamos que llegar a una situación en la que a es el componente más pequeño de la suma, y el más grande aún no es b . Sin embargo, en ese punto no podemos eliminar a , porque la suma es claramente menor que n (ya que falta b ), por lo que debemos agregar valores primero hasta que agreguemos b y presionemos n exactamente. Esto prueba (4).
Tomando estas cosas juntas: sabemos que el primer par de pasos nos da un valor máximo de A002024 (n) . Sabemos que el valor máximo de la descomposición final es A212652 (n) . Y sabemos que este máximo se incrementa una vez en cada par de pasos. Por lo tanto, la expresión final es 2 * ( A212652 (n) - A002024 (n) + 1) . Esta fórmula casi funciona para números triangulares, excepto que para aquellos solo necesitamos 1 paso en lugar de 2, por lo que corregimos el resultado con la función indicadora de los números triangulares (o su inverso, lo que sea más conveniente).
Finalmente, en cuanto a la implementación. Para la primera secuencia, estoy usando la fórmula MIN (impar d | n; n / d + (d-1) / 2) de OEIS. Resulta guardar algunos bytes si tomamos el factor 2 en esta expresión para obtener MIN (impar d | n; 2n / d + d-1) , porque ese -1 se cancela con el +1 en mi primera versión de f (n) que codifica directamente los dos casos para números triangulares y no triangulares. En el código, esto es:
Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]
Para la última secuencia ( 1, 2, 2, 3, 3, 3, ...
), podemos usar una forma cerrada simple:
⌊(2#)^.5+.5⌋
Y finalmente, la función del indicador inverso de los números triangulares es 0 siempre que 8n + 1 sea un cuadrado perfecto. Esto se puede expresar en Mathematica como
⌈Sqrt[8#+1]~Mod~1⌉
Hay muchas maneras de expresar estas dos últimas secuencias y cambiar un desplazamiento constante entre ellas, por lo que estoy seguro de que aún no es una implementación óptima, pero espero que esto pueda dar a otros un punto de partida para buscar nuevos enfoques en sus propios idiomas
Desde que me metí en todos estos problemas, aquí hay una gráfica de la secuencia hasta n = 1000 (también podría calcular 100k en un par de segundos, pero realmente no muestra ninguna información adicional):
Puede ser interesante analizar las variaciones sobre esas líneas muy rectas, pero se lo dejaré a otra persona ...