Counting integer points inside a sphere of radius R and dimension D - c++

I am trying to write an efficient algorithm that counts the number of points inside a Sphere of Radius R and Dimension D. The sphere is always at the origin. Suppose we have a sphere of dimension 2 (circle) with radius 5.
My strategy is to generate all possible points within the first quadrant, so for the above example we know that (1,2) is in the circle, so must all + / - combinations of that point which is simply dimension squared. So for each point found in a single quadrant of an n-dimensional sphere we add 2 ^ dimension to the total count.
I'm not sure if there is a much more efficient solution to this problem but this is what I have so far in terms of implementation.
int count_lattice_points(const double radius, const int dimension) {
int R = static_cast<int>(radius);
int count = 0;
std::vector<int> points;
std::vector<int> point;
for(int i = 0; i <= R; i++)
points.push_back(i);
do {
for(int i = 0; i < dimension - 1; i++)
point.push_back(points.at(i));
if(isPointWithinSphere(point, radius)) count += std::pow(2,dimension);
point.clear();
}while(std::next_permutation(points.begin(), points.end()));
return count + 3;
}
What can I fix or improve in this situation ?

For 2D case this is Gauss's circle problem. One possible formula:
N(r) = 1 + 4 * r + 4 * Sum[i=1..r]{Floor(Sqrt(r^2-i^2))}
(central point + four quadrants, 4*r for points at the axis, others for in-quadrant region).
Note that there is no known simple closed math expression for 2D case.
In general your idea with quadrants, octants etc is right, but checking all the points is too expensive.
One might find the number of ways to compose all squares from 0 to r^2 from 1..D
integer squares (extension of (4) formula).
Note that combinatorics would help to make calculation faster. For example, it is enough to find the number of ways to
make X^2 from D natural squares, and multiply by 2^D (different sign combinations); find the number of ways to make X^2 from D-1 natural squares, and multiply by D*2^(D-1) (different sign combinations + D places for zero addend) etc
Example for D=2, R=3
addends: 0,1,4,9
possible sum compositions number of variants
0 0+0 1
1 0+1,1+0 2*2=4
2 1+1 4
4 0+4,4+0 2*2=4
5 1+4,4+1 2*4=8
8 4+4 4
9 0+9,9+0 2*2=4
-------------------------------------
29

I presented my algorithm for 2D here (with some source code and an ugly but handy illustration):
https://stackoverflow.com/a/42373448/5298879
It's around 3.4x faster than MBo's counting points between the origin and the edge of the circle in one of the quarters.
You just imagine an inscribed square and count only one-eighth of what's outside that square inside that circle.
public static int gaussCircleProblem(int radius) {
int allPoints=0; //holds the sum of points
double y=0; //will hold the precise y coordinate of a point on the circle edge for a given x coordinate.
long inscribedSquare=(long) Math.sqrt(radius*radius/2); //the length of the side of an inscribed square in the upper right quarter of the circle
int x=(int)inscribedSquare; //will hold x coordinate - starts on the edge of the inscribed square
while(x<=radius){
allPoints+=(long) y; //returns floor of y, which is initially 0
x++; //because we need to start behind the inscribed square and move outwards from there
y=Math.sqrt(radius*radius-x*x); // Pythagorean equation - returns how many points there are vertically between the X axis and the edge of the circle for given x
}
allPoints*=8; //because we were counting points in the right half of the upper right corner of that circle, so we had just one-eightth
allPoints+=(4*inscribedSquare*inscribedSquare); //how many points there are in the inscribed square
allPoints+=(4*radius+1); //the loop and the inscribed square calculations did not touch the points on the axis and in the center
return allPoints;
}

An approach similar to that described by MBo, including source code, can be found at
https://monsiterdex.wordpress.com/2013/04/05/integer-lattice-in-n-dimensional-sphere-count-of-points-with-integer-coordinates-using-parallel-programming-part-i/.
The approach consists in finding partitions of the radius, and then for each partition in the sphere compute the number of ways it can be represented in the sphere by both permuting coordinates and flipping the signs of nonzero coordinates.

Related

How to find the closest square of the given point

I have a 2-D array of squares (square shape), Each square has 50 units length and x, y co-ordinates. The distance between the squares is 5 units. The x, y co-ordinates are the bottom left corner of the square. Now, given any point(x,y co-ordinates) how can i find the closest square to this point.
square **sq = new square*[10];
for(int i=0;i<10;++i){
sq[i]=new square[10];
}
int m=0, n=0;
for(int i=0;i<10;++i){
m=0;
for(int j=0;j<10;++j){
sq[i][j].setCoOrdinates(m,n);
m+=55;
}
n+=55;
}
// Given a point (x, y) how can i find the index (i, j) of closest square to this point.
Let's rigorously define the definition of distance from a square to a point: "The minimum of all lengths from the point (x,y) to some point within the rectangle".
This gives some clear rules for defining the distance to a rectangle. For any rectangle, if the point(x,y) is directly above, below, to the left of, or to the right of the sides of the rectangle, the minimum distance to the rectangle is the straight line drawn either vertically or horizontally through the point. For instance, if your point is (40, 90) and your rectangle's bottom-left is (0,0) (and it is a 50x50 square), you can draw a vertical line through your point and the distance is min(90-(0+50), 90-0)
If the point is not directly above, below, left of, or right of the sides of the square, then the closest distance is to the closest of the four corners. You can simply take the min of all the distances to the four corners, which can be found by using the distance formula.
Simply apply this logic to each of your squares in your array and you should be good to go! Time O(NM) where n is the number of rows of squares and M is the number of columns of squares. In other words, O(number of squares you have). Space O(1).
Lets start with the simpler problem: All rectangles are 55 units wide, ie there is no empty space between them...
The best container is the one that you do not need. There is a simple relation between i and j index of a square in the array and its m and n coordinates:
const int distance = 55;
int m(int i) { return i*distance; }
int n(int j) { return m(j); }
As the relation is linear, you can invert it:
int i(int m) { return m / distance; }
int j(int n) { return i(n); }
Using integer arithmetics is fine here, because we get the same result as if we had used floating points and then rounded down.
This is already the full solution for the simpler problem. Given coordinats m and n the closest square is at index i(m),j(n).
Now lets introduce the gap:
cosnt int width = 50;
const int gap = 5;
Now we have to distinguish two possibilities: The given coordinats are inside a square or outside. When it is outside there are two candidates for the cloest square.
int i_with_gap(int m) {
int i = m / distance;
// point is inside the square?
if (m % distance <= width) return i;
// point is closer to square at index i?
if (m % distance <= width+ gap/2.0) return i;
// otherwise i+1 is closer
return i+1;
}

Using Standard Cartesian Circle formula to draw circle in graphics mode (C++)

I wanted to draw a circle using graphics.h in C++, but not directly using the circle() function. The circle I want to draw uses smaller circles as it's points i.e. The smaller circles would constitute the circumference of the larger circle. So I thought, if I did something like this, it would work:
{
int radius = 4;
// Points at which smaller circles would be drawn
int x, y;
int maxx = getmaxx();
int maxy = getmaxy();
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
//Cartesian cirle formula >> (X-h)^2 + (Y-k)^2 = radius^2
//Effectively, this nested loop goes through every single coordinate on the screen
int gmode = DETECT;
int gdriver;
initgraph(&gmode, &gdriver, "");
for(x = 0; x<maxx; x++)
{
for(y = 0; y<maxy; y++)
{
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
circle(x, y, 5) //Draw smaller circle with radius 5
} //at points which satisfy circle equation only!
}
}
getch();
}
This is when I'm using graphics.h on Turbo C++ as this is the compiler we're learning with at school.
I know it's ancient.
So, theoretically, since the nested for loops check all the points on the screen, and draw a small circle at every point that satisfies the circle equation only, I thought I would get a large circle of radius as entered, whose circumference constitutes of the smaller circles I make in the for loop.
However, when I try the program, I get four hyperbolas (all pointing towards the center of the screen) and when I increase the radius, the pointiness (for lack of a better word) of the hyperbolas increase, until finally, when the radius is 256 or more, the two hyperbolas on the top and bottom intersect to make a large cross on my screen like : "That's it, user, I give up!"
I came to the value 256 as I noticed that of the radius was a multiple of 4 the figures looked ... better?
I looked around for a solution for quite some time, but couldn't get any answers, so here I am.
Any suggestions???
EDIT >> Here's a rough diagram of the output I got...
There are two issues in your code:
First: You should really call initgraph before you call getmaxx and getmaxy, otherwise they will not necessarily return the correct dimensions of the graphics mode. This may or may not be a contributing factor depending on your setup.
Second, and most importantly: In Turbo C++, int is 16-bit. For example, here is circle with radius 100 (after the previous initgraph order issue was fixed):
Note the stray circles in the four corners. If we do a little debugging and add some print-outs (a useful strategy that you should file away for future reference):
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
printf(": (%d-%d)^2 + (%d-%d)^2 = %d^2\n", x, h, y, k, radius);
circle(x, y, 5); //Draw smaller circle with radius
} //at points which satisfy circle equation only!
You can see what's happening (first line is maxx and maxy, not shown in above snippet):
In particular that circle at (63, 139) is one of the corners. If you do the math, you see that:
(63 - 319)2 + (139 - 239)2 = 75536
And since your ints are 16-bit, 75536 modulo 65536 = 10000 = the value that ends up being calculated = 1002 = a circle where it shouldn't be.
An easy solution to this is to just change the relevant variables to long:
maxx, maxy
x, y
h, k
So:
long x, y;
...
initgraph(...);
...
long maxx = getmaxx();
long maxy = getmaxy();
...
long h = maxx / 2;
long k = maxy / 2;
And then you'll end up with correct output:
Note of course that like other answers point out, since you are using ints, you'll miss a lot of points. This may or may not be OK, but some values will produce noticeably poorer results (e.g. radius 256 only seems to have 4 integer solutions). You could introduce a tolerance if you want. You could also use a more direct approach but that might defeat the purpose of your exercise with the Cartesian circle formula. If you're into this sort of thing, here is a 24-page document containing a bunch of discussion, proofs, and properties about integers that are the sum of two squares.
I don't know enough about Turbo C++ to know if you can make it use 32-bit ints, I'll leave that as an exercise to you.
First of all, maxx and maxy are integers, which you initialize using some functions representing the borders of the screen and then later you use them as functions. Just remove the paranthesis:
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
Then, you are checking for exact equality to check whether a point is on a circle. Since the screen is a grid of pixels, many of your points will be missed. You need to add a tolerance, a maximum distance between the point you check and the actual circle. So change this line:
if(((x-h)*(x-h)) + ((y-k)*(y-k)) == radius*radius)
to this:
if(abs(((x-h)*(x-h)) + ((y-k)*(y-k)) - radius*radius) < 2)
Introduction of some level of tolerance will solve the problem.
But it is not wise to check all the points in graphical window. Would you change an approach? You can draw needed small circles without checks at all:
To fill all big circle circumference (with RBig radius), you need NCircles small circles with RSmall radius
NCircles = round to integer (Pi / ArcSin(RSmall / RBig));
Center of i-th small circle is at position
cx = mx + Round(RBig * Cos(i * 2 * Pi / N));
cy = my + Round(RBig * Sin(i * 2 * Pi / N));
where mx, my - center of the big circle

Distance between two cells in a 2D matrix

I have a 2D matrix represented as a vector of values, an index representing the first cell and a pair of coordinate representing the second cell.
vector<double> matrix;
auto index = 10;
auto x1 = index % width;
auto y1 = index / width;
auto x2 = ...
auto y2 = ...
I need to find the distance between these two cells, where the distance is equals to 1 for the first "ring" of the 8 neighbor cells, 2 for the second ring, and so on.
Is there a way faster than the euclidean distance?
What you need is something like a modified Manhattan Distance. I think there may be a specific name for your use case, but I don't know it. Anyway, this is how I'd do it.
Suppose the two points are x rows away and y columns away. Then x+y is the Manhattan Distance. But in your case, diagonal movements are also allowed. So, if you moved diagonally towards the point initially, you'd cover the smaller of x and y, with some amount remaining in the other. You can then move horizontally/vertically to cover the remaining distance. Hence, the distance by your metric would be max(x,y).
Given points (x1,y1) and (x2,y2), the answer would be max(|x1-x2|,|y1-y2|)

In c++, how do I create point locations arbitrarily?

I'm trying to program a simulation. Originally I'd randomly create points like so...
for (int c = 0; c < number; c++){
for(int d = 0; d < 3; d++){
coordinate[c][d] = randomrange(low, high);
}
}
Where randomrange() is an arbitrary range randomizer, number is the amount of created points, and d represents the x,y,z coordinate. It works, however I want to take things further. How would I define a known shape? Say I want 80 points on a circle's circumference, or 500 that form the edges of a cube. I can explain well on paper, but have a problem describing the process as coding. This doesn't pertain to the question, but I end up taking the points to txt file and then use matlab, scatter3 to plot the points. Creating the "shape" points is my issue.
Both a circle and a cube edges set are 1-dimensional sets, so you can represent them as real intervals. For a circle it's straightforward: use an interval (0, 2pi) and transform a random value phi from the interval into a point:
xcentre + R cos(phi), ycentre + R sin(phi)
For a cube you have 12 segments, so use interval (0, 12) and split a random number from the interval into an integer part and a fraction. Then use the integer as an edge number and the fraction as a position inside the edge.
Easy variant:
First think of the min/max x/y values (separately; to reduce the faulty values for the step below), generate some coordinates matching this range, and then check if it fulfills eg. a^2+b^2=r^2 (circle)
If not, try again.
Better, but only possible for certain shapes:
Generate a radius between (0-max) and an angle (0-360)
(or just an angle if it should be on the circle border)
and use some math (sin/cos...) to transform it into x and y.
http://en.wikipedia.org/wiki/Polar_coordinate_system

Algorithm for finding number of squares in a given circle

Here is my drawing: CLICK
I need to write a program, that will find the number of squares(1x1), that we can draw into a circle of given radius.The squares can only by drawn fully and placed like lego blocks- one on another. In some cases, vertexes of squares can lie on the circle.
Examples: for 1- it makes 0, for 2- it gives four, for 3- 16 squares, for 4-32, for 5-52.
I have written something, but it doesn't work fine for 5+ (I mean- radius bigger than 5). Here it goes: CLICK. In my code- r is radius of the circle, sum is the sum of all squares and height is the height of triangles I try to "draw" into the circle (using Pythagorean theorem).
Now- any help? Is my algorithm even correct? Should I change something?
There is Gauss's Circle Problem that gives a formula to count integer points inside the circle of given radius. You may use this logic to count squares that lie in the circle.
N = 4 * Sum[i=1..R] (Floor(Sqrt((R^2-i^2)))
example:
R = 3
i=1 n1 = Floor(Sqrt(9-1))~Floor(2.8)=2
i=2 n2 = Floor(Sqrt(9-4))~Floor(2.2)=2
i=3 n2 = Floor(Sqrt(9-9))=0
N=4*(n1+n2+n3)=16
First off - circle with a radius of 5 fits 60 1x1 squares, not 52. My bet would be someone didn't count the points {[3,4],[3,-4],[4,3],[4,-3],[-4,3],[-4,-3],[-3,4],[-3,-4]} when drawing that on paper and counting by hand, being unsure whether they are right on the circle or just outside of it. They are exactly on the circle.
Second - MBo's answer brought me here - I sometimes search StackOverflow for Gauss Circle Problem to see if someone suggested some new, fun algorithm.
Third - here's the code:
int allSquares=0,
squaredRadius=radius*radius,
sideOfQuarterOfInscribedSquare=(int)(long)(radius/sqrt(2));
for(int x=sideOfQuarterOfInscribedSquare+1;
x<radius;
x++){
allSquares+=(long)sqrt(squaredRadius-x*x);
}
allSquares= allSquares*8+4*sideOfQuarterOfInscribedSquare*sideOfQuarterOfInscribedSquare;
return allSquares;
What it does is just count the squares inside one-eighth of the circle, outside an inscribed square. Sorry for my hipster formatting and overly verbose variable names.