Retina , 66 63 45 43 36 bytes
^()(\1(?<1>.\1))+(\1(.(?(4).\4)))*$
A pesar del título que dice Retina, esta es solo una expresión regular .NET que acepta representaciones unarias de números de Loeschian.
Las entradas 999 y 1000 toman bastante menos de un segundo.
Pruébalo en línea! (La primera línea permite un conjunto de pruebas separadas por salto de línea, y las dos siguientes se encargan de la conversión a unario por conveniencia).
Explicación
La solución se basa en la clasificación de que la entrada se puede escribir como i*i + j*(i + j)positiva iy no negativa j(ya que no tenemos que manejar la entrada 0), y eso n*nes solo la suma de los primeros nenteros impares. Jugar al golf fue un ejercicio interesante en referencias avanzadas.
Una "referencia hacia adelante" es cuando coloca una referencia hacia atrás dentro del grupo al que hace referencia. Por supuesto, eso no funciona cuando el grupo se usa por primera vez, ya que no hay nada a lo que hacer referencia todavía, pero si lo coloca en un bucle, la referencia inversa obtiene la captura de la iteración anterior cada vez. Esto a su vez, le permite construir una captura más grande con cada iteración. Esto se puede usar para crear patrones muy compactos para cosas como números triangulares, cuadrados y números de Fibonacci.
Como ejemplo, usando el hecho de que los cuadrados son solo sumas de los primeros nenteros impares, podemos hacer coincidir una entrada cuadrada como esta:
(^.|..\1)+$
En la primera iteración, ..\1no puede funcionar, porque \1todavía no tiene un valor. Entonces comenzamos con la ^.captura de un solo personaje en grupo 1. En las iteraciones posteriores, ^.ya no coincide debido al ancla, pero ahora ..\1es válido. Coincide con dos caracteres más que la iteración anterior y actualiza la captura. De esta manera emparejamos números impares crecientes, obteniendo un cuadrado después de cada iteración.
Ahora, desafortunadamente, no podemos usar esta técnica tal como está. Después de hacer coincidir i*i, necesitamos obtener itambién, para poder multiplicarlo por j. Una manera simple (pero larga) de hacer esto es hacer uso del hecho de que la coincidencia i*irequiere iiteraciones, de modo que hemos capturado las icosas en grupo 1. Ahora podríamos usar grupos de equilibrio para extraer esto i, pero como dije, eso es costoso.
En cambio, descubrí una forma diferente de escribir esta "suma de enteros impares consecutivos" que también produce iun grupo de captura al final. Por supuesto, el itercer número es justo 2i-1. Esto nos da una manera de incrementar la referencia directa solo en 1 en cada iteración. Esa es esta parte:
^()(\1(?<1>.\1))+
Esto ()simplemente empuja una captura vacía al grupo 1(inicializando ia 0). Esto es bastante equivalente a la ^.|solución simple anterior, pero usar |en este caso sería un poco más complicado.
Luego tenemos el bucle principal (\1(?<1>.\1)). \1coincide con el anterior i, (?<1>.\1)luego actualiza el grupo 1con i+1. En términos de lo nuevo i , acabamos de hacer coincidir los 2i-1personajes. Exactamente lo que necesitamos.
Cuando terminamos, hemos combinado algunos cuadrados i*iy el grupo 1todavía tiene ipersonajes.
La segunda parte está más cerca de la simple coincidencia cuadrada que mostré arriba. Ignoremos la referencia a 1por ahora:
(.(?(4).\1))*
Esto es básicamente lo mismo que (^.|..\4)*, excepto que no podemos usarlo ^porque no estamos al comienzo de la cadena. En su lugar, utilizamos un condicional, para que coincida con el adicional .\1solo cuando ya hemos usado group 4. Pero en efecto esto es exactamente lo mismo. Esto nos da j*j.
Lo único que falta es el j*itérmino. Combinamos esto con el j*jhecho de que el j*jcómputo todavía toma jiteraciones. Entonces, para cada iteración también avanzamos el cursor icon \1. Solo tenemos que asegurarnos de no escribir eso en el grupo 4, porque eso podría interferir con números impares consecutivos. Así es como llegamos a:
(\1(.(?(4).\1)))*