您想按距离增加的顺序迭代可能的位移(即移位)。由于所有位移都是整数,所以位移的平方需要是两个平方的和。以下 python 代码跟踪每个x位移的下一个可能的y位移。它生成对列表。每对表示位移坐标。单个列表中的所有元素与原点的距离相同,而后面列表中的元素将具有更大的距离。因此,至少在距离方面,遍历内部列表的顺序无关紧要。你甚至可能想要随机化这些。
def iter_distance(maxr = 10):
r = 0
d = [0]
while r <= maxr:
m = maxr*maxr + 1
for x, y in enumerate(d):
sq = x*x + y*y
if sq < m:
m = sq
b = []
if sq == m:
b.append((x, y))
for x, y in b:
d[x] = y + 1
if b[-1][0] == r:
r += 1
d.append(0)
yield (b +
[(x, -y) for x, y in b if y] +
[(-x, y) for x, y in b if x] +
[(-x, -y) for x, y in b if x*y])
for lst in iter_distance():
marker = '*'
for x, y in lst:
print("{:5} {:5} {:10} {}".format(x, y, x*x + y*y, marker))
marker = ' '
输出的第一行如下所示:
0 0 0 *
0 1 1 *
1 0 1
0 -1 1
-1 0 1
1 1 2 *
1 -1 2
-1 1 2
-1 -1 2
0 2 4 *
2 0 4
0 -2 4
-2 0 4
1 2 5 *
2 1 5
1 -2 5
2 -1 5
-1 2 5
-2 1 5
-1 -2 5
-2 -1 5
2 2 8 *
2 -2 8
-2 2 8
-2 -2 8
0 3 9 *
3 0 9
0 -3 9
-3 0 9
对于高达 400 的距离(即传递 400 作为maxr
参数),您将获得 37,556 个不同距离的 502,625 行,因此您希望动态生成这些,而不是将它们硬编码到应用程序中。但是,您可以使用这些数字来检查您的实施,以防我们中的一个人出错。
如果你关心性能,你可以使用优先级队列而不是数组,这样写:
#include <queue>
#include <utility>
#include <cmath>
#include <iostream>
#include <iomanip>
class displacement {
private:
int _d;
int _x;
int _y;
public:
displacement() : _d(0), _x(0), _y(0) {}
displacement(int x, int y) : _d(x*x + y*y), _x(x), _y(y) {}
int x() const { return _x; }
int y() const { return _y; }
int sqd() const { return _d; }
bool operator<(const displacement& d) const { return sqd() > d.sqd(); }
};
static void print2(int x, int y, int sqd) {
std::cout << std::setw(10) << x << ' '
<< std::setw(10) << y << ' '
<< std::setw(20) << sqd << ' '
<< std::endl;
}
static void print1(int x, int y, int sqd) {
print2(x, y, sqd);
if (y)
print2(x, -y, sqd);
if (x) {
print2(-x, y, sqd);
if (y)
print2(-x, -y, sqd);
}
}
int main(int argc, char** argv) {
int maxr = 400;
int maxrsq = maxr*maxr;
std::priority_queue<displacement> q;
q.push(displacement(0, 0));
while (q.top().sqd() <= maxrsq) {
const displacement& d = q.top();
int x = d.x();
int y = d.y();
int sqd = d.sqd();
print1(x, y, sqd);
q.pop();
q.push(displacement(x, y + 1));
if (x == y) {
q.push(displacement(x + 1, y + 1));
}
else {
print1(y, x, sqd);
}
}
}
在这种情况下,队列包含单个位移,结果将以任意(可能是实现定义的)顺序打印相同距离的单个位移,而不会将它们收集到列表中。只有给定位移的镜像才会立即打印。这里的代码采用了完全的 8 重对称,因此任何一次存储在队列中的元素数量甚至比目前生成的最大距离还要少,除了最开始的时候。