11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)

35

Dado un entero positivo N , su tarea es devolver el número de pasos requeridos por el siguiente algoritmo para llegar a N :

  1. Encontrar el número más pequeño triangular T i tal que T i  ≥ N . Construya la lista correspondiente L = [1, 2, ..., i] .

  2. Si bien la suma de los términos de L es mayor que N , elimine el primer término de la lista.

  3. Si la suma de los términos de L ahora es menor que N , incremente i y añádalo a la lista. Continúa con el paso 2.

Nos detenemos tan pronto como se alcanza N. Solo el primer paso se ejecuta sistemáticamente. Los pasos 2 y 3 pueden no procesarse en absoluto.

Ejemplos

A continuación se muestra un ejemplo para N = 11 :

Ejemplo

Entonces, la salida esperada para N = 11 es 4 .

Otros ejemplos:

  • N = 5 - Comenzamos con T 3 = 1 + 2 + 3 = 6 , seguido de 2 + 3 = 5 . Resultado esperado: 2 .
  • N = 10 : solo se requiere el primer paso porque 10 es un número triangular: T 4 = 1 + 2 + 3 + 4 = 10 . Salida esperada: 1 .

Primeros 100 valores

A continuación se muestran los resultados para 1 ≤ N ≤ 100 :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

Reglas

  • Puede escribir un programa completo o una función que imprima o devuelva el resultado.
  • Usted está obligado a procesar cualquier N ≤ 65.536 en menos de un minuto en el hardware de gama media.
  • Con suficiente tiempo, su programa / función debería funcionar teóricamente para cualquier valor de N que sea compatible de forma nativa con su idioma. Si no es así, explique por qué en su respuesta.
  • Este es el código de golf, por lo que gana la respuesta más corta en bytes.
Arnauld
fuente
Relacionado. (Sospecho que ya sabes sobre este, pero solo lo
publico
¿Cuál es el valor máximo de N que necesitamos manejar?
Lucas
@Luke Consulte las reglas actualizadas.
Arnauld

Respuestas:

4

Jalea , 29 31 bytes

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

Un enlace monádico que devuelve el resultado (N = 65536 tarda menos de dos segundos).

Pruébalo en línea!

¿Cómo?

Para una explicación detallada del algoritmo, vea la fantástica publicación de Martin Ender .

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

La implementación del programa completo de 29 bytes que creé del algoritmo descrito toma 4 min 30 para N = 65536 en mi computadora portátil, por lo que supongo que no cuenta.

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

Usar un ciclo while para cada paso 3 y reutilizarlo como paso 1 es igual en longitud a lo que puedo manejar al inicializar la lista, ya que no verificar en el paso 3 significa construir una lista hasta que no quede nada y luego encontrar el primer índice del valor:

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i
Jonathan Allan
fuente
25

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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):

ingrese la descripción de la imagen aquí

Puede ser interesante analizar las variaciones sobre esas líneas muy rectas, pero se lo dejaré a otra persona ...

Martin Ender
fuente
Finalmente me tomé el tiempo de leer tu respuesta a fondo. Esto es brillante. Tenga en cuenta que (3) ya se suponía en el algoritmo (el paso n. ° 3 es un if , no un tiempo ), pero la prueba es, por supuesto, muy bienvenida.
Arnauld
@Arnauld Gracias. :) Debo haber pasado por alto / mal entendido la parte if / while. Lo bueno es que no hace la diferencia entonces.
Martin Ender
7

Mathematica, 72 bytes

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

Función pura tomando un argumento entero.

Cómo funciona

For[ ... ]

Un Forbucle

l=u=c=k=0

Inicialización; establecer l(inferior), u(superior), c(contador) y k(suma) a 0.

k!=#

Condición; repetir mientras kno es igual a la entrada.

c++

Incremento; Incrementar el contador c.

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

Cuerpo

If[#>k, ... ]

Si la entrada es mayor que k:

While[#>k,k+=++u]

Mientras la entrada es mayor que k, incremente ue incremente ken u.

Si la entrada no es mayor que k:

While[#<k,k-=l++]

Mientras que la entrada es menor que k, decremento kpor le incremento l.

( ... ;c)

Regresa cdespués del bucle.

JungHwan Min
fuente
1
For[,...]late While[...].
Martin Ender
5

Python 2 , 104 bytes

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

Pruébalo en línea!

Alterna entre agregar términos al final de la lista y eliminar términos desde el principio.

Mathmandan
fuente
5

Haskell , 70 63 68 64 bytes

EDITAR:

  • -7 bytes: eliminó un espacio, dos signos y algunos paréntesis al negar el sentido de a. Se corrigieron errores fuera de uno en la explicación.
  • +5 bytes: Argh, completamente perdida que 65.536 requisito, y resulta que (1) las potencias de 2 son especialmente caros, ya que sólo recibe un golpe cuando se llega a la cantidad en sí (2) de manera que se suma distancias largas (que se envuelven alrededor cero) todo el tiempo. Reemplazó la suma con una fórmula matemática.
  • -4 bytes: ajustado ay blinealmente para obtener términos en la fórmula de suma para cancelar.

1#1 es una función anónima que toma y devuelve un entero.

Usar como (1#1) 100.

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

Pruébalo en línea!

Cómo funciona

  • (a#b)nrepresenta el paso actual de cálculo. a, bson números 1, 3, 5, .., mientras que npueden ser positivos o negativos dependiendo del paso.
    • Cuando en el paso 1 o 3, representa la lista [(a+1)/2,(a+3)/2..(b-1)/2]y el número de objetivo -n.
    • Cuando en el paso 2, representa la lista [(b+1)/2,(b+3)/2..(a-1)/2]y el número de objetivo n.
  • La extraña correspondencia entre a, by las listas es para poder hacer un resumen con la expresión corta s=a*a-b*b.
    • En los pasos 1 y 3, esto es lo mismo que s= -8*sum[(a+1)/2..(b-1)/2].
    • En el paso 2, esto es lo mismo que s=8*sum[(b+1)/2..(a-1)/2].
  • La ramificación se realiza mediante listas de comprensión que producen elementos en un solo caso cada una, y sumando los resultados.
    • Si s>8*n, entonces bse incrementa en 2 antes de recurrir.
      • En los pasos 1 y 3, esto aumenta la lista, mientras que en el paso 2, esto lo reduce.
    • Si s<8*n, a continuación, la recursión cambia el paso mediante el canje ay b, y negando n, y se añade 1 al resultado.
    • Si s==8*n, entonces ninguna de las dos comprensiones de la lista da ningún elemento, entonces la suma es 0.
  • (1#1) nrepresenta una "etapa 2" ficticia antes de comenzar, que se cambia inmediatamente al paso 1, desde donde se crea la lista [1..0]=[].
Ørjan Johansen
fuente
4

PHP> = 7.0, 74 bytes

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

usa el operador de la nave espacial

Pruébalo en línea!

Expandido

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps
Jörg Hülsermann
fuente
¿Qué es $argn?
chx
@chx Una variable que está disponible cuando PHP desde la línea de comandos con la opción -R php.net/manual/en/features.commandline.options.php
Jörg Hülsermann
Guau. Nunca escuché de -Rmucho menos argvo argi. Sabía de argc y argv, por supuesto. Muy interesante, gracias.
chx
4

DO, 94 91 bytes

Probar en línea

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}
Khaled.K
fuente
Uso extenso en variables no inicializadas oO
YSC
@YSC en C, los enteros declarados globalmente no inicializados se ponen a cero en tiempo de compilación. leer más
Khaled.K
Olvidé esto. Gracias por este recordatorio.
YSC
Para su información, he publicado otra respuesta C . Al menos uno de los trucos que utilicé no funcionará con otros compiladores (los que faltan return), pero para los que sí lo hacen, siéntete libre de incorporarlos en tu respuesta.
hvd
3

JavaScript (ES6), 82 bytes

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

Fragmento de prueba

R. Kap
fuente
Lamento decir esto, pero cada ↄ cuenta como 3 bytes. Supongo que no importa ya que es trivialmente renombrable.
Ørjan Johansen
@ ØrjanJohansen Gracias por recordármelo. Realmente debería recordar calificar mi código por bytes en lugar de por longitud. No creo que haya un consenso de la comunidad sobre "variables trivialmente renombrables", así que edité la publicación. Oh bien.
R. Kap
3
El fragmento falla con “Demasiada recursividad” en 6553. 6553 funciona localmente en el Nodo (6.9.1), pero 65536 no (“Se excedió el tamaño máximo de la pila de llamadas”).
eush77
3

dc , 61 bytes

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

Pruébalo en línea!

Explicación

Macro recursiva principal:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

Esta macro:

  1. Encuentra el número triangular mínimo que excede el número actual en la pila (usando la fórmula de raíz triangular modificada ).
  2. Comprueba si suma triangular S representa el número actual exactamente. Sale si lo hace.
  3. Vaya al paso 1 con S+N(sobre-aproximación) o S-N(sub-aproximación), la elección alterna entre iteraciones.

Cuando sale, el rastro dejado en la pila le dice al programa principal cuántas iteraciones tomó.

eush77
fuente
3

Python 3, 150 138 bytes

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

Registro de cambios:

  • Cambiado agregar a + =, eliminado más (gracias musicman523, Loovjo; -12 bytes)
L3viatán
fuente
1
El paso 2 puede eliminar uno o varios términos a la vez de la lista (como 1, 2 y 3 en el ejemplo para N = 11), pero se cuenta como un paso en ambos sentidos.
Arnauld
@Arnauld pasó por alto eso; fijo.
L3viathan
1
¿Puedes explicar por qué elsees necesario? Creo que siempre se elseejecuta, porque el ciclo siempre termina normalmente (sin break), y parece funcionar bien sin él .
musicman523
Puede omitir la A=l.appendparte y usarla l+=[x]en su lugar.
Loovjo
3

Lote, 126 bytes

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

Explicación: les cero si el paso 2 nunca se ejecutó. Esto permite nrealizar un seguimiento del número de iteraciones del paso 3. Dado que el algoritmo nunca se detiene en el paso 3, por lo tanto, debe haber ejecutado el paso 1 una vez y el paso 2 n+1veces para un total de n+n+2pasos. Sin embargo, si el parámetro es un número triangular, el paso 2 nunca se ejecuta, por lo que debemos restar un paso.

Neil
fuente
3

Python 2, 86 81 bytes

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

Pruébalo en línea!

Calcula el caso de prueba 655360.183s en TIO.


Esta versión recursiva a 84 bytes no puede calcular todos los valores hasta 65536:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

Pruébalo en línea!

ovs
fuente
2

Mathematica, 92 bytes

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

Función pura que toma un argumento entero y devuelve un entero.

Las variables ay brepresentan los números iniciales y finales (que cambian constantemente) en la suma considerada, mientras que qrepresentan el total acumulado (de los números de a+1a b); trealiza un seguimiento de todos los valores qencontrados hasta ahora. Después de inicializar estas variables, el Forbucle sigue ejecutándose If[q<#,q+=++b,q-=++a], lo que agrega un nuevo número al final o resta el número en el frente como lo indica la especificación, hastaq igual a la entrada.

Ahora solo tenemos que extraer el número de pasos de tla lista de qvalores encontrados en el camino. Por ejemplo, cuando la entrada es 11, el Forciclo sale con tigual {0,1,3,6,10,15,14,12,9,15,11}. La mejor manera que encontré para calcular el número de pasos a partir de esto es contar cuántas veces cambian las diferencias de arriba a abajo; eso es lo que hace el comando detallado Length@Split@Sign@Differences@t, pero sospecho que se puede mejorar.

Greg Martin
fuente
2

C (tcc), 71 bytes (61 + 10)

Argumentos de línea de comando (incluido un espacio):

-Dw=while

Fuente:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

Cómo funciona:

ccuenta la cantidad de pasos. my Malmacenar el mínimo y el máximo del rango, sla suma. Inicialmente, todos son cero.

Continuamente, cse incrementa y sse compara con n. Mientras sean desiguales:

  • Si ces impar, entonces, siempre y cuando s<n, agregue un número entero al final del rango: aumente Men uno y sen M.

  • Si ces par, entonces, siempre y cuando s>n, eliminar un número entero desde el inicio de la gama: disminución spor m, e incrementar mpor uno.

Cuando el ciclo sale, cse ha incrementado demasiadas veces. Disminuirlo produce el resultado correcto, y se calcula en el registro correcto para que actúe como valor de retorno.

De manera divertida, usa exactamente los mismos nombres de variables que la respuesta C de Khaled.K . No se copian.

hvd
fuente
1

Perl 6 , 114 bytes

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(inspirado en una implementación anterior de Haskell )

Pruébelo
Se ejecuta con una entrada de 65536 en menos de 45 segundos en mi computadora, pero no he podido ejecutarlo en menos de 60 segundos con TIO.run.
Tengo Rakudo v2017.04 +, donde tiene v2017.01 .
Rakudo / NQP / MoarVM obtiene optimizaciones casi a diario, por lo que podría haber una cantidad de ellas desde el ínterin que sean necesarias para obtenerla en un plazo breve.


Expandido

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

Tenga en cuenta que Rakudo tiene una optimización para Range.sumque no tenga que recorrer todos los valores.

Brad Gilbert b2gills
fuente