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
Ci sono state molte soluzioni proposte per questo problema scritte in vari linguaggi di programmazione, ma sembrano tutte derivare dallo stesso approccio contorto. Prenderò in considerazione il problema più generale del calcolo di una spirale che può essere espressa in modo conciso usando l'induzione.
Caso base: inizia da (0, 0), vai avanti di 1 quadrato, gira a sinistra, vai avanti di 1 quadrato, gira a sinistra. Passaggio induttivo: sposta in avanti di n + 1 quadrati, gira a sinistra, sposta in avanti di n + 1 quadrati, gira a sinistra.
L'eleganza matematica nell'esprimere questo problema suggerisce fortemente che dovrebbe esserci un semplice algoritmo per calcolare la soluzione. Tenendo presente l'astrazione, ho scelto di non implementare l'algoritmo in un linguaggio di programmazione specifico ma piuttosto di pseudo-codice.
Innanzitutto prenderò in considerazione un algoritmo per calcolare solo 2 iterazioni della spirale usando 4 coppie di loop while. La struttura di ciascuna coppia è simile, ma distinta a sé stante. All'inizio questo può sembrare folle (alcuni loop vengono eseguiti solo una volta) ma passo dopo passo eseguirò trasformazioni fino a quando non arriveremo a 4 coppie di loop identici e quindi possono essere sostituiti con una singola coppia posizionata all'interno di un altro loop. Questo ci fornirà una soluzione generale di calcolo delle iterazioni senza usare alcun condizionale.
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 prima trasformazione che faremo è l'introduzione di una nuova variabile d, per la direzione, che contiene il valore +1 o -1. La direzione cambia dopo ogni coppia di anelli. Poiché conosciamo il valore di d in tutti i punti, possiamo moltiplicare ciascun lato di ciascuna disuguaglianza per esso, regolare di conseguenza la direzione della disuguaglianza e semplificare eventuali moltiplicazioni di d da una costante ad un'altra costante. Questo ci lascia con il seguente.
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
Ora notiamo che sia x * d sia RHS sono numeri interi in modo da poter sottrarre qualsiasi valore reale tra 0 e 1 dall'RHS senza influenzare il risultato della disuguaglianza. Scegliamo di sottrarre 0,5 dalle disuguaglianze di ogni altra coppia di loop while per stabilire più di un modello.
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
Ora possiamo introdurre un'altra variabile m per il numero di passi che facciamo ad ogni coppia di cicli 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
Infine, vediamo che la struttura di ciascuna coppia di loop while è identica e può essere ridotta a un singolo loop posizionato all'interno di un altro loop. Inoltre, per evitare di usare numeri con valori reali ho moltiplicato il valore iniziale di m; il valore m viene incrementato di; ed entrambi i lati di ciascuna disuguaglianza di 2.
Questo porta alla soluzione mostrata all'inizio di questa risposta.