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の正方形を前方に移動して左折します。
この問題を表現する数学的優雅さは、解を計算するための単純なアルゴリズムがあるべきであることを強く示唆しています。抽象化を念頭に置いて、特定のプログラミング言語でアルゴリズムを実装するのではなく、疑似コードとして実装することを選択しました。
最初に、whileループの4つのペアを使用して、スパイラルの2回の反復を計算するアルゴリズムを検討します。各ペアの構造は似ていますが、それ自体は異なります。これは最初は奇妙に見えるかもしれません(一部のループは1回しか実行されない)が、同一のループの4つのペアに到達するまで段階的に変換を行って、別のループ内に配置された1つのペアで置き換えることができます。これにより、条件を使用せずに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
最初に行う変換は、方向に対して、値+1または-1を保持する新しい変数dの導入です。ループの各ペアの後に方向が切り替わります。すべての点で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はどちらも整数であるため、不等式の結果に影響を与えることなく、RHSから0〜1の任意の実数値を減算できることに注意してください。パターンをさらに確立するために、whileループの他のすべてのペアの不等式から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
ここで、whileループの各ペアで実行するステップ数を表す別の変数mを導入できます。
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です。
これは、この回答の冒頭に示した解決策につながります。