Как бы вы решили проблему нахождения точек (целочисленной) сетки внутри круга с центром в начале оси, с результатами, упорядоченными по норме, как на расстоянии от центра, в C ++?
Я бы не использовал std::pair
для удержания очков.Я бы создал свой собственный более описательный тип.
struct Point {
int x;
int y;
int square() const { return x*x + y*y; }
Point(int x = 0, int y = 0)
: x(x), y(y) {}
bool operator<(const Point& pt) const {
if( square() < pt.square() )
return true;
if( pt.square() < square() )
return false;
if( x < pt.x )
return true;
if( pt.x < x)
return false;
return y < pt.y;
}
friend std::ostream& operator<<(std::ostream& os, const Point& pt) {
return os << "(" << pt.x << "," << pt.y << ")";
}
};
Эта структура данных (вероятно) точно такого же размера, что и два целых, она меньше чем сопоставима, она назначаема и легко печатается.
Алгоритм проходит по всем действительным точкам, которые удовлетворяют x = [0, радиусу] && y = [0, x] && (x, y) внутри круга:
std::set<Point>
GetListOfPointsInsideCircle(double radius = 1) {
std::set<Point> result;
// Only examine bottom half of quadrant 1, then
// apply symmetry 8 ways
for(Point pt(0,0); pt.x <= radius; pt.x++, pt.y = 0) {
for(; pt.y <= pt.x && pt.square()<=radius*radius; pt.y++) {
result.insert(pt);
result.insert(Point(-pt.x, pt.y));
result.insert(Point(pt.x, -pt.y));
result.insert(Point(-pt.x, -pt.y));
result.insert(Point(pt.y, pt.x));
result.insert(Point(-pt.y, pt.x));
result.insert(Point(pt.y, -pt.x));
result.insert(Point(-pt.y, -pt.x));
}
}
return result;
}
Я выбрал std::set
для хранения данных по двум причинам:
- Он хранится в порядке сортировки, поэтому мне не нужно
std::sort
его и - Он отклоняет дубликаты, поэтому мне не нужно беспокоиться о точках, отражение которых идентично
Наконец, использовать этот алгоритм очень просто:
int main () {
std::set<Point> vp = GetListOfPointsInsideCircle(2);
std::copy(vp.begin(), vp.end(),
std::ostream_iterator<Point>(std::cout, "\n"));
}