let x = 0
let y = 0
let d = 1
let m = 1
while true
while 2 * x * d < m
print(x, y)
x = x + d
while 2 * y * d < m
print(x, y)
y = y + d
d = -1 * d
m = m + 1
Ha habido muchas soluciones propuestas para este problema escritas en varios lenguajes de programación, sin embargo, todas parecen provenir del mismo enfoque intrincado. Voy a considerar el problema más general de calcular una espiral que se puede expresar de manera concisa usando inducción.
Caso base: Comience en (0, 0), avance 1 casilla, gire a la izquierda, avance 1 casilla, gire a la izquierda. Paso inductivo: Avanzar n + 1 casillas, girar a la izquierda, avanzar n + 1 casillas, girar a la izquierda.
La elegancia matemática de expresar este problema sugiere fuertemente que debería haber un algoritmo simple para calcular la solución. Teniendo en cuenta la abstracción, he optado por no implementar el algoritmo en un lenguaje de programación específico, sino como un pseudocódigo.
Primero consideraré un algoritmo para calcular solo 2 iteraciones de la espiral usando 4 pares de bucles while. La estructura de cada par es similar, pero distinta por derecho propio. Esto puede parecer una locura al principio (algunos bucles solo se ejecutan una vez), pero paso a paso haré transformaciones hasta llegar a 4 pares de bucles que son idénticos y, por lo tanto, se pueden reemplazar con un solo par colocado dentro de otro bucle. Esto nos proporcionará una solución general para calcular n iteraciones sin usar ningún condicionante.
let x = 0
let y = 0
//RIGHT, UP
while x < 1
print(x, y)
x = x + 1
while y < 1
print(x, y)
y = y + 1
//LEFT, LEFT, DOWN, DOWN
while x > -1
print(x, y)
x = x - 1
while y > -1
print(x, y)
y = y - 1
//RIGHT, RIGHT, RIGHT, UP, UP, UP
while x < 2
print(x, y)
x = x + 1
while y < 2
print(x, y)
y = y + 1
//LEFT, LEFT, LEFT, LEFT, DOWN, DOWN, DOWN, DOWN
while x > -2
print(x, y)
x = x - 1
while y > -2
print(x, y)
y = y - 1
La primera transformación que haremos es la introducción de una nueva variable d, para la dirección, que contiene el valor +1 o -1. La dirección cambia después de cada par de bucles. Dado que conocemos el valor de d en todos los puntos, podemos multiplicar cada lado de cada desigualdad por él, ajustar la dirección de la desigualdad en consecuencia y simplificar cualquier multiplicación de d por una constante a otra constante. Esto nos deja con lo siguiente.
let x = 0
let y = 0
let d = 1
//RIGHT, UP
while x * d < 1
print(x, y)
x = x + d
while y * d < 1
print(x, y)
y = y + d
d = -1 * d
//LEFT, LEFT, DOWN, DOWN
while x * d < 1
print(x, y)
x = x + d
while y * d < 1
print(x, y)
y = y + d
d = -1 * d
//RIGHT, RIGHT, RIGHT, UP, UP, UP
while x * d < 2
print(x, y)
x = x + d
while y * d < 2
print(x, y)
y = y + d
d = -1 * d
//LEFT, LEFT, LEFT, LEFT, DOWN, DOWN, DOWN, DOWN
while x * d < 2
print(x, y)
x = x + d
while y * d < 2
print(x, y)
y = y + d
Ahora notamos que tanto x * d como RHS son enteros, por lo que podemos restar cualquier valor real entre 0 y 1 del RHS sin afectar el resultado de la desigualdad. Elegimos restar 0.5 de las desigualdades de cada par de bucles while para establecer un patrón más.
let x = 0
let y = 0
let d = 1
//RIGHT, UP
while x * d < 0.5
print(x, y)
x = x + d
while y * d < 0.5
print(x, y)
y = y + d
d = -1 * d
//LEFT, LEFT, DOWN, DOWN
while x * d < 1
print(x, y)
x = x + d
while y * d < 1
print(x, y)
y = y + d
d = -1 * d
//RIGHT, RIGHT, RIGHT, UP, UP, UP
while x * d < 1.5
print(x, y)
x = x + d
while y * d < 1.5
print(x, y)
y = y + d
d = -1 * d
//LEFT, LEFT, LEFT, LEFT, DOWN, DOWN, DOWN, DOWN
while x * d < 2
print(x, y)
x = x + d
while y * d < 2
print(x, y)
y = y + d
Ahora podemos introducir otra variable m para el número de pasos que damos en cada par de bucles while.
let x = 0
let y = 0
let d = 1
let m = 0.5
//RIGHT, UP
while x * d < m
print(x, y)
x = x + d
while y * d < m
print(x, y)
y = y + d
d = -1 * d
m = m + 0.5
//LEFT, LEFT, DOWN, DOWN
while x * d < m
print(x, y)
x = x + d
while y * d < m
print(x, y)
y = y + d
d = -1 * d
m = m + 0.5
//RIGHT, RIGHT, RIGHT, UP, UP, UP
while x * d < m
print(x, y)
x = x + d
while y * d < m
print(x, y)
y = y + d
d = -1 * d
m = m + 0.5
//LEFT, LEFT, LEFT, LEFT, DOWN, DOWN, DOWN, DOWN
while x * d < m
print(x, y)
x = x + d
while y * d < m
print(x, y)
y = y + d
Finalmente, vemos que la estructura de cada par de bucles while es idéntica y puede reducirse a un solo bucle colocado dentro de otro bucle. Además, para evitar el uso de números con valor real, he multiplicado el valor inicial de m; el valor m se incrementa en; y ambos lados de cada desigualdad por 2.
Esto lleva a la solución que se muestra al comienzo de esta respuesta.