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
Existem muitas soluções propostas para esse problema escritas em várias linguagens de programação, no entanto, todas elas parecem resultar da mesma abordagem complicada. Vou considerar o problema mais geral de calcular uma espiral que pode ser expressa de forma concisa usando indução.
Caso base: comece em (0, 0), avance 1 quadrado, vire à esquerda, avance 1 quadrado, vire à esquerda. Passo indutivo: avançar n + 1 quadrados, virar à esquerda, avançar n + 1 quadrados, virar à esquerda.
A elegância matemática de expressar esse problema sugere fortemente que deve haver um algoritmo simples para calcular a solução. Mantendo a abstração em mente, decidi não implementar o algoritmo em uma linguagem de programação específica, mas como pseudo-código.
Primeiro, considerarei um algoritmo para calcular apenas 2 iterações da espiral usando 4 pares de loops while. A estrutura de cada par é semelhante, mas distinta por si só. Isso pode parecer louco no começo (alguns loops são executados apenas uma vez), mas passo a passo farei transformações até chegarmos a 4 pares de loops que são idênticos e, portanto, podem ser substituídos por um único par colocado dentro de outro loop. Isso nos fornecerá uma solução geral de iterações de computação sem o uso de condicionais.
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
A primeira transformação que faremos é a introdução de uma nova variável d, para direção, que contém o valor +1 ou -1. A direção muda após cada par de loops. Como conhecemos o valor de d em todos os pontos, podemos multiplicar cada lado de cada desigualdade por ele, ajustar a direção da desigualdade de acordo e simplificar qualquer multiplicação de d por uma constante para outra constante. Isso nos deixa com o seguinte.
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
Agora observamos que x * d e o RHS são números inteiros, portanto podemos subtrair qualquer valor real entre 0 e 1 do RHS sem afetar o resultado da desigualdade. Optamos por subtrair 0,5 das desigualdades de todos os outros pares de loops while, a fim de estabelecer mais um padrão.
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
Agora podemos introduzir outra variável m para o número de etapas que seguimos em cada par de loops 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 a estrutura de cada par de loops while é idêntica e pode ser reduzida a um único loop colocado dentro de outro loop. Além disso, para evitar o uso de números reais, multipliquei o valor inicial de m; o valor m é incrementado por; e ambos os lados de cada desigualdade por 2.
Isso leva à solução mostrada no início desta resposta.