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
Il y a eu de nombreuses solutions proposées pour ce problème écrites dans divers langages de programmation, mais elles semblent toutes provenir de la même approche alambiquée. Je vais considérer le problème plus général du calcul d'une spirale qui peut être exprimée de manière concise en utilisant l'induction.
Cas de base: Commencez à (0, 0), avancez d'1 case, tournez à gauche, avancez d'1 case, tournez à gauche. Pas inductif: Avancez de n + 1 carrés, tournez à gauche, avancez de n + 1 carrés, tournez à gauche.
L'élégance mathématique de l'expression de ce problème suggère fortement qu'il devrait y avoir un algorithme simple pour calculer la solution. En gardant à l'esprit l'abstraction, j'ai choisi de ne pas implémenter l'algorithme dans un langage de programmation spécifique mais plutôt sous forme de pseudo-code.
Je vais d'abord considérer un algorithme pour calculer seulement 2 itérations de la spirale en utilisant 4 paires de boucles while. La structure de chaque paire est similaire, mais distincte en soi. Cela peut sembler fou au début (certaines boucles ne sont exécutées qu'une seule fois) mais pas à pas, je vais faire des transformations jusqu'à ce que nous arrivions à 4 paires de boucles identiques et pouvant donc être remplacées par une seule paire placée à l'intérieur d'une autre boucle. Cela nous fournira une solution générale de calcul de n itérations sans utiliser de conditionnelles.
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 première transformation que nous allons faire est l'introduction d'une nouvelle variable d, pour la direction, qui contient la valeur +1 ou -1. La direction change après chaque paire de boucles. Puisque nous connaissons la valeur de d en tous points, nous pouvons multiplier chaque côté de chaque inégalité par elle, ajuster la direction de l'inégalité en conséquence et simplifier toute multiplication de d par une constante à une autre constante. Cela nous laisse avec ce qui suit.
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
Maintenant, nous notons que x * d et le RHS sont des entiers, nous pouvons donc soustraire toute valeur réelle entre 0 et 1 du RHS sans affecter le résultat de l'inégalité. Nous choisissons de soustraire 0,5 des inégalités de chaque autre paire de boucles while afin d'établir davantage un modèle.
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
Nous pouvons maintenant introduire une autre variable m pour le nombre de pas que nous faisons à chaque paire de boucles 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
Enfin, on voit que la structure de chaque paire de boucles while est identique et peut se réduire à une seule boucle placée à l'intérieur d'une autre boucle. Aussi, pour éviter d'utiliser des nombres réels, j'ai multiplié la valeur initiale de m; la valeur m est incrémentée de; et les deux côtés de chaque inégalité par 2.
Cela conduit à la solution indiquée au début de cette réponse.