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
Запропоновано багато варіантів вирішення цієї проблеми, написаних різними мовами програмування, однак, схоже, всі вони випливають з того самого згорнутого підходу. Я збираюся розглянути більш загальну проблему обчислення спіралі, яка може бути виражена стисло за допомогою індукції.
Базова справа: Почніть з (0, 0), рухайтеся вперед на 1 квадрат, поверніть вліво, рухайтеся вперед на 1 квадрат, поверніть вліво. Індуктивний крок: рухайтесь вперед n + 1 квадратів, поверніть вліво, рухайтеся вперед n + 1 квадратів, поверніть вліво.
Математична витонченість вираження цієї проблеми наголошує, що для обчислення рішення повинен бути простий алгоритм. Маючи на увазі абстракцію, я вирішив не реалізувати алгоритм певною мовою програмування, а як псевдо-код.
Спочатку я розгляну алгоритм для обчислення всього 2 ітерацій спіралі, використовуючи 4 пари циклів while. Структура кожної пари схожа, але сама по собі виразна. Спочатку це може здатися божевільним (деякі петлі виконуються лише один раз), але крок за кроком я буду робити перетворення, поки ми не отримаємо 4 пари циклів, які однакові, і, отже, можна замінити одну пару, розміщену всередині іншого циклу. Це дасть нам загальне рішення обчислення n ітерацій без використання будь-яких умов.
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
Перше перетворення, яке ми зробимо, - це введення нової змінної d для напряму, яка має значення +1 або -1. Напрямок перемикається після кожної пари петель. Оскільки ми знаємо значення d у всіх точках, ми можемо помножити на нього кожну сторону кожної нерівності, відповідно відрегулювати напрямок нерівності та спростити будь-яке множення d на постійну до іншої постійної. Це залишає нам наступне.
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
Тепер відзначимо, що і x * d, і RHS є цілими числами, тому ми можемо відняти будь-яке дійсне значення від 0 до 1 від RHS, не впливаючи на результат нерівності. Ми вирішимо відняти 0,5 від нерівностей кожної іншої пари циклів у той час, щоб встановити більше шаблону.
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
Тепер ми можемо ввести ще одну змінну m для кількості кроків, які ми робимо для кожної пари циклів 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
Нарешті, ми бачимо, що структура кожної пари циклів while однакова і може бути зведена до однієї петлі, розміщеної всередині іншого циклу. Крім того, щоб уникнути використання дійсних значущих чисел, я помножив початкове значення m; значення m збільшується на; і обидві сторони кожної нерівності по 2.
Це призводить до рішення, показаного на початку цієї відповіді.