Algorithm for pool ball movement calcualtion - c

I need help or idea how to make an algorithm for a pool game/program.
I need this as a project for my collage so this needs to be written as simply as possible using only basic and loops,sadly I can't use arrays or functions.
The whole point of the program is to calculate how many steps/hits on the corner of the table will the ball need to reach its starting point (Assumed that ball has infinite velocity and that there are no other balls etc.. Simply we assume that its possible)
We need to look at the table as a coordinate system with (m x n) dimensions, and we need to input starting point of the ball (x1,y1) and the point where the ball will hit the table for the first time (x2,y2) based on that info we need to make an algorithm that will calculate how many hits/steps will the ball need to reach its starting point.
I had an idea to use the fact that ball will have same angle on impact which means that if the ball hits the table on 30 degrees angle it will repel off the table with same angle to the other side. So because the tables is set as a coordinate system I could use atan to calculate the angle and then with that info to calculate the distance from the other point. I made a program with the info I know but this won't work because this is only one calculation (I guess that I will need to use for loop(s) to calculate everything. And I have a big problem in understanding how to set the edge of the table because some of my calculations goes outside the (m x n) space.
I will attach 2 pictures that were given to us as examples and part of the code that I use. I hope that someone can help me and I'm sorry if I made a lot of grammar mistakes, English is not my primary language.
Thanks in advance.
PICTURES :
Orange dot is the starting point, orange line is the first hit that we input,everything else needs to be calculated:
Same as picture one but more complex example:
MY CODE:
#include <stdio.h>
#include <math.h>
#define PI 3.14159265359
int main() {
int i;
double x1,y1,x2,y2;
int n,m;
double angle;
double xPrime,yPrime;
double distance;
double m1;
printf("Enter the staring point (x1,y1) and first hit point(x2,y2) ");
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
printf("Enter the dimensions (n x m ) ");
scanf("%d %d",&n,&m);
m1=(y2-y1)/(x2-x1);
angle=atan(m1);
distance =sqrt( pow((x2-x1),2) + pow((y2-y1),2));
xPrim = x2 + (-distanca * cos(ugao));
yPrim = y2 + (distanca * sin(ugao));
return 0;
}

You should consider the X and Y axes separately. The discussion below assumes that the ball initially starts moving in the positive direction on both axes. If it doesn't then flip stuff around to the symmetrical situation so that it does.
Given the table size by M x N, the starting point (x0,y0), and the first hit (x1,y1):
Let T be the time it takes to get from (x0,y0) to (x1,y1), so the initial velocity (in units per T) is (vx,vy) = (x1-x0, y1-y0)
Considering the X axis, the ball will hit a wall at time (M-x0)/vx, measured in units of T. It will get back to the starting X coordinate at time (2M-2x0)/vx. It will hit the other wall at time (2M-x0)/vx and get back to the start position again at time 2M/vx. Then the cycle will repeat.
So, the times at which it will get back to the start position are (2aM - 2x0)/vx and 2aM/vx, for all integer a>0. The times it will hit a wall are (2aM - x0) and ((2a-1)M - x0).
Similarly, on the Y axis, the times it will get back to the start position are (2bN - 2y0)/vy and 2bN/vy, for all integer b>0. The times it will hit a wall are (2bN - y0) and ((2b-1)N - y0).
So, to find times when the ball gets back to the start, solve:
(2aM - 2x0)/vx = (2bN - 2y0)/vy or
(2aM - 2x0)/vx = 2bN/vy or
2aM/vx = (2bN - 2y0)/vy or
2aM/vx = 2bN/vy
for the smallest integers a>0 and b>0.
All of these reduce to linear Diophantine equations that are readily solved: https://en.wikipedia.org/wiki/Diophantine_equation
Once you know how long it takes to get back to the start, you can use the other equations above to calculate how many wall hits were made.

Related

If a point lies in the vicinity of a logarithmic spiral : Not returning points near the center

I have a set of data points, which I want to test if they lie on a logarithmic spiral arm for given parameters. The following program seems to work, but does not return any points close to the center of my plane, which contains all the data points. The image attached shows that my program does not seem to find any points which overlap with the spiral near the center. Here is the link :
http://imgur.com/QbNPg5S. Moreover, it seems to show two spirals in the overlapped points, which is another issue.
int main(){
float radial[10000]={0}, angle[10000]={0}; // my points of interest
float theta, r_sp; // radius and the angle theta for the spiral
Construct a spiral which lies in the same plane as my sources (green in the image)
for (j=0;j<=PI*10; j++){
theta=j*3./10;
r_sp=a_sp*exp(b_sp*theta);
Calculating the radial and angular components from x and y given coordinates (read from a file)
for (m=0;m<=30;m++){
radial[m]=pow((x_comp*x_comp+y_comp*y_comp),0.5);
angle[m]= atan2f(y_comp, x_comp);
Change the range from [ -pi, pi] to [0, 2*pi] consistent with "theta" of spiral
if (angle[m] < 0.){
angle[m]=angle[m]+PI;
}
Check if the point (radial and angle) lies on/around the spiral. For the realistic effect, I am considering the points at a radial distance "dr=0.5" (jitter) away from the "r_sp" value of the spiral.
if (fabs(r_sp-radial[m]) <=0.5 && fabs(theta-angle[m]) <= 1.0e-2){
printf("%f\t%f\t%f\t%f\n",l[k],b[k],ns[k],radial[m]);
}
}
}
return 0;
}
You check the conditions only for the first turn of spiral that lies in angle range 0..2*Pi.
At first you have to estimate potential turn number from r = radial[m]
r=a*exp(b*t)
r/a=exp(b*t)
ln(r/a)=b*t
t = ln(r/a) / b
turnnumber = Floor(ln(r/a) / b)
Now you can use
angle[m] = YourAngleFromArctan + 2 * Pi * turnnumber
to compare

Restricted 3 body simulation not working correctly

I am currently trying to do an assignment where i have to write a simulation for the restricted 3 body gravitational problem, with two fixed masses and one test mass. The information i have been given on the problem is: Check out this link and here is my program so far:
#include<stdlib.h>
#include<stdio.h>
#include <math.h>
int main (int argc, char* argv[])
{
double dt=0.005, x[20000],y[20000],xv,yv,ax,ay,mneg,mpos,time,radius=0.01;
int n,validation=0;
FILE* output=fopen("proj1.out", "w");
printf("\n");
if((argv[1]==NULL) || (argv[2]==NULL) || (argv[3]==NULL) || (argv[4]==NULL) || (argv[5]==NULL) || (argv[6]==NULL))
{
printf("************************ ERROR! ***********************\n");
printf("** Not enough comand line arguments input. **\n");
printf("** Please run again with the correct amount (6). **\n");
printf("*******************************************************\n");
validation=1;
goto VALIDATIONFAIL;
}
if((sscanf(argv[1], "%lf", &mneg)==NULL) || (sscanf(argv[2], "%lf", &mpos)==NULL) || (sscanf(argv[3], "%lf", &x[0])==NULL) ||
(sscanf(argv[4], "%lf", &y[0])==NULL) || (sscanf(argv[5], "%lf", &xv)==NULL) || (sscanf(argv[6], "%lf", &yv)==NULL) )
{
printf("************************* ERROR! ************************\n");
printf("** Input values must be numbers. Please run again with **\n");
printf("** with numerical inputs (6). **\n");
printf("*********************************************************\n");
validation=1;
goto VALIDATIONFAIL;
}
sscanf(argv[1], "%lf", &mneg);
sscanf(argv[2], "%lf", &mpos);
sscanf(argv[3], "%lf", &x[0]);
sscanf(argv[4], "%lf", &y[0]);
sscanf(argv[5], "%lf", &xv);
sscanf(argv[6], "%lf", &yv);
x[1]=x[0]+(xv*dt);
y[1]=y[0]+(yv*dt);
for(n=1;n<10000;n++)
{
if(x[n-1]>=(1-radius) && x[n-1]<=(1+radius) && y[n-1]>=(0-radius) && y[n-1]<=(0+radius))
{
printf("Test mass has collided with M+ at (1,0), Exiting...\n");
goto EXIT;
}
else if(x[n-1]>=(-1-radius) && x[n-1]<=(-1+radius) && y[n-1]>=(0-radius) && y[n-1]<=(0+radius))
{
printf("Test mass has collided with M- at (-1,0), Exiting...\n");
goto EXIT;
}
else
{
double dxn = x[n] + 1;
double dxp = x[n] - 1;
double mnegdist = pow((dxn*dxn + (y[n]*y[n])), -1.5);
double mposdist = pow((dxp*dxp + (y[n]*y[n])), -1.5);
ax = -(mpos*dxp*mposdist+mneg*dxn*mnegdist);
ay = -(mpos*y[n]*mposdist+mneg*y[n]*mnegdist);
x[n+1]=((2*x[n])-x[n-1] +(dt*dt*ax));
y[n+1]=((2*y[n])-y[n-1]+(dt*dt*ay));
fprintf(output, "%lf %lf\n",x[n-1], y[n-1]);
}
}
VALIDATIONFAIL:
printf("\n");
return(EXIT_FAILURE);
EXIT:
return(EXIT_SUCCESS);
}
My program is working to certain extent but i am getting some weird problems that i hope someone can help me with.
The main issue is that when the test mass gets to a point in its trajectory when it should go off and start to orbit about the other mass it instead just shoots off on a straight line to infinity! at first i thought it was that the masses were colliding so i put in the radius check, but in some cases this does work, in some cases it doesn't, and in some cases the masses collide earlier on before the trajectory goes wrong anyway so this clearly isn't the issue. I am not sure if i have explained that all too well so here is a picture to show you what i mean. (the simulation on the right is from here)
However, this is not always the case, sometimes instead of going in a straight line, the trajectory just goes crazy when it should go over to the other mass, like this:
I really have absolutely no idea whats going on i have spent days trying to figure this out but just cant seem to get anywhere, so any help in identifying where my problem is would be very much appreciated.
This is just too long to fit in a comment and I also might be of use to future visitors.
The proper choice of timestep for a given computation is not an easy task. The family of Verlet integrators are symplectic, which means that they preserve the phase space volume and hence should preserve the total energy of the system given infinite precision and an infinitely small timestep, but unfortunately real computers operate with finite precision and the human life is too short in order for us to wait for an infinite number of timesteps.
The Verlet integrator, like the one that you have implemented and the velocity Verlet scheme, have global error which is O(Δt2). It means that the algorithm is only quadratically sensitive to the timestep and in order to greatly improve the precision, one has to decrease the timestep accordingly by as many times as the square root of the desired precision improvement factor. Click on the into button of the Flash applet that you compare your trajectories with and you'll see that it uses a completely different integrator - the Euler-Cromer algorithm (also known as semi-implicit Euler method). It has different precision given the same timestep (actually it is worse than that of the Verlet scheme given the same timestep) and hence you cannot and should not directly compare both trajectories, rather only their statistical properties (e.g. mean energy, mean velocity, etc.)
My point was that you have to decrease the timestep, because it is too large to handle the cases when the test body comes too close to one of the gravitational centres. There is another problem hidden here and it is the finite numerical precision. Observe this term:
double dxp = x[n] - 1;
double mposdist = pow((dxp*dxp + (y[n]*y[n])), -1.5);
Whenever you subtract two closely valued floating point numbers (x[n] and 1.0), a very unfortunate event happens, known as precision loss as most of the higher significant bits in their mantissas cancel each other and in the end, after the normalisation step, you get a number with much less significant bits than the original two numbers. This precision loss gets even bigger as the result is then squared and used as a denominator. Note that this mostly happens near the axis of symmetry of the system where y[n] comes close to 0. Otherwise y[n] might be big enough so that dxp*dxp is only a tiny correction to the value of y[n]*y[n]. The net result is that the force would come out totally wrong near each fixed mass and would usually be greater in magnitude than the actual force. This is prevented in your case as you test for the point being outside the prescribed radius.
Greater forces lead to greater displacements given a fixed timestep. This also leads to an artificial increase in the total energy of the system, i.e. the test mass would tend to move faster than in a finer simulation. It also might happen that the test body ends up so close to the gravitational centre, that the huge force times the square of the timestep might give so huge a displacement, that your test mass would end up much far away, but this time with the increased total energy it would result in high kinetic energy and the body would practically be ejected from the simulation volume. This could also happen even if you compute the force with infinite precision - simply the displacement between two timesteps might be so large (because of the large timestep) that the system would make an unrealistic jump in the phase space to a completely different energy isosurface. And with gravity (as well as with electrostatics) it is so easy to get to such a case as the force increases as 1/r^2 and near the radius it is many orders of magnitude stronger than in the initial state.
One might come up with different rules of a thumb to estimate the size of the timestep given the largest expected force value, but in general the higher the maximum force, the lower the timestep should be. These kind of things can usually be roughly estimated given the initial conditions, which saves a lot of failed simulations due to "ejection" effects.
Now as the Verlet schemes are symplectic, the best way to control the correctness of the simulation is to observe the total energy of the system. Note that the velocity Verlet integrator is a bit better as it is numerically more stable (but still it has the same dependence of the accuracy on the square of the timestep). With the standard Verlet scheme you can get an approximation of the speed v[i] by taking (x[i+1] - x[i-1])/(2*dt). With the velocity Verlet, the speed is included explicitly in the equations.
Either way, it would make sense to take the speed and to compute the total energy of the system at each timestep and to observe the value. If the timestep is Just Right (tm), then the total should be almost conserved with relatively small oscillations around the mean value. If it goes crazy upwards, then your timestep is too big and should be decreased.
Decreasing the timestep increases the run-time of the simulation accordingly. One could also observe that in the far field the forces are small, the point moves slowly and a long timestep is just fine. Shorter timestep would not improve the solution there but would only increase the run-time. That's why people have invented the multi-timestep algorithms and also the adaptive timestep algorithms that automatically refine the solutions in the near field. Also a different method to compute the forces might be applied there by transforming the equations so as to not include subtraction of closely valued variables.
(well, this came out way larger than even several comments)
I found it difficult to understand your code, so I will try to be as helpful as I can and apologize, if I am telling you things you already know.
The best way I have found to calculate the physics for simulations involving gravity is to use Newtons Law of Universal Gravitation. This is given by the formula:
F = ( ( -G * M1 * M2 ) / ( R * R ) ) * r_unit_vector;
Where:
G ~= 6.67e-11,
M1 is the mass of the first object,
M2 is the mass of the second object,
R is the distance between the two objects: sqrt(pow(X2 - X1, 2) + pow(Y2 - Y1, 2))
X1 is the X-coordinate of object 1,
X2 is the X-coordinate of object 2,
Y1 is the Y-coordinate of object 1,
Y2 is the Y-coordinate of object 2.
r_unit_vector is a unit vector pointing from object 2 to object 1
struct r_unit_vector_struct{
double x, y;
}r_unit_vector;
r_unit_vector has a x component which is object 2's x-coordinate - object 1's x-coordinate,
r_unit_vector has a y component which is object 2's y-coordinate - object 1's y-coordinate.
To make r_unit_vector a unit vector, you must divide (both the x aand y components separately) by its length, which is given by sqrt(pow(r_unit_vector.x, 2) + pow(r_unit_vector.y - Y1, 2))
And you should all be ready to go! Hopefully this makes sense. If not, I will write you a class to do this stuff or explain it further if I can!

Rotating a 2-d array by 90 degrees

A frequent question that props up during array manipulation exercises is to rotate a two dimensional array by 90 degrees. There are a few SO posts that answer how to do it in a variety of programming languages. My question is to clarify one of the answers that is out there and explore what sort of thought-process is required in order to get to the answer in an organic manner.
The solution to this problem that I found goes as follows:
public static void rotate(int[][] matrix,int n)
{
for( layer = 0;layer < n/2;++layer){
int first = layer;
int last = n -1 - layer;
for(int i = first;i<last;++i){
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last-offset][first];
matrix[last-offset][first] = matrix[last][last-offset];
matrix[last][last-offset] = matrix[i][last];
matrix[i][last] = top;
}
}
}
I have somewhat of an idea what the code above is trying to do, it is swapping out the extremities/corners by doing a four-way swap and doing the same for the other cells separated by some offset.
Stepping through this code I know it works, what I do not get is the mathematical basis for the above given algorithm. What is the rationale behind the 'layer','first','last' and the offset?
How did 'last' turn out to be n-1-layer? Why is the offset i-first? What is the offset in the first place?
If somebody could explain the genesis of this algorithm and step me through the thought process to come up with the solution, that will be great.
Thanks
The idea is to break down the big task (rotating a square matrix) into smaller tasks.
First, a square matrix can be broken into concentric square rings. The rotation of a ring is independent from the rotation of other rings, so to rotate the matrix just rotate each of the rings, one by one. In this case, we start at the outermost ring and work inward. We count the rings using layer (or first, same thing), and stop when we get to the middle, which is why it goes up to n/2. (It is worth checking to make sure this will work for odd and even n.) It is useful to keep track of the "far edge" of the ring, using last = n - 1 - layer. For instance, in a 5x5 matrix, the first ring starts at first=0 and ends at last=4, the second ring starts at first=1 and ends at last=3 and so on.
How to rotate a ring? Walk right along the top edge, up along the left edge, left along the bottom edge and down along the right edge, all at the same time. At each step swap the four values around. The coordinate that changes is i, and the number of steps is offset. For example, when walking around the second ring, i goes {1,2,3} and offset goes {0,1,2}.

Genetic Programming with the Mandelbrot Set

I'm reading a chapter in this fascinating book about using genetic programming to interactively evolve images. Most of the function set is comprised of simple arithmetic and trig functions (which really operation on and return images). These functions make up the internal nodes of the parse trees that encode our images. The leaves of the tree, or the terminal values, are random numbers and x,y coordinates.
There's a section about adding iterative functions of the complex plane to the function set:
Say the genetics inserts a particular Mandelbrot set as a node somewhere in
a bushy tree. The function expects two arguments: mandel(cReal, cImag), treating
them as real and imaginary coordinates in the complex plane. If the genome
just happened to supply the pixel coordinates (x,y), and mandel() were the root
node, you would get the familiar Mset. But chances are that cReal and cImag are themselves the results of whole branches of functions, with many instances of coordinates
x,y scattered out among the leaves. Enter the iteration loop, orbit
around for a while, and finally escape with some measure of distance to the Mset
attractor, such as the number of iterations.
My question is how would you make a Mandelbrot set renderer as a function that takes the real and imaginary coordinates of a point on the complex plane as arguments and returns a rendering of the Mandelbrot set?
I'm not sure if this actually answers your question, but my understanding of the text you quoted simply says that the mandel function is just another function (like multiplication, min, max, addition, etc) that can appear in your genetic program.
The mandel function, like the multiplication function, takes two arguments (in_1 and in_2) and returns a single value. Whereas the multiplication function just returns in_1 * in_2, the mandel function might do something like this:
int mandel(int in_1, int in_2) {
x = 0
y = 0
iteration = 0
max_iteration = 1000
while( x*x + y*y <= (2*2) && iteration < max_iteration ) {
xtemp = x*x - y*y + in_1
y = 2*x*y + in_2
x = xtemp
++iteration
}
if( iteration == max_iteration ) return 0
else return iteration
}
If your whole genetic program tree consists of nothing but the mandel function with one input as x and the other input as y, then repeatedly evaluating your program for a bunch of different (x,y) values and saving the result will give you a nice picture of the Mandelbrot set.
Of course, the neat thing about genetic programming is that the inputs can be fancier than just x and y. For example, what would the result look like if one input was x and the other input was x + 2*y? Or if one input was x and the other was mandel(x,y)?

algorithm to find overlaps

Basically I've got some structs of type Ship which are going to go on a board which can have a variable width and height. The information about the ships is read in from a file, and I just need to know the best way to make sure that none of the ships overlap.
Here is the structure of Ship:
int x // x position of first part of ship
int y // y position of first part of ship
char dir // direction of the ship, either 'N','S','E' or 'W'
int length // length of the ship
Also, what would be a good way to handle the directions. Something cleaner than using a switch statement and using a different condition for each direction.
Any help would be greatly appreciated!
You could keep a boolean array of the entire grid, initially initialized to "false." For each ship, for each location the ship covers, check if the location is "false." If it is,
set it to "true". If not, then some other ship is on the location.
This algorithm is linear in the total area of all the ships, but also requires extra space
proportional to the number of locations on the board.
This is the same thing as a test whether rectangles intersect, I think your code would be simpler if you don't think of these ships as a point,length, and direction but as a rectangle.
So convert this
int x // x position of first part of ship
int y // y position of first part of ship
char dir // direction of the ship, either 'N','S','E' or 'W'
int length // length of the ship
to this (allow negative cx & cy to get N,S,E,W)
int x // x position of first part of ship
int y // y position of first part of ship
int cx // length of the ship in X
int cy // length of the ship in Y
or this
int left // x position of Eastern part of the ship
int top // y position of Northernmost part of ship
int right // x position of Westernmost part of the ship
int bottom // y position of Southernmost part of ship
bool orientation; // so we can tell East from West or North from South.
Then a simple function can determine if two ships intersect.
bool DoShipsIntersect(Ship * a, Ship * b)
{
if ((a->right < b->left) || (b->right < a->left))
return false;
if ((a->bottom < b->top) || (b->bottom < a->top))
return false;
return true;
}
A brute force compare of every ship to every other ship should be quite fast as long as you don't have thousands of ships.
Unless you have a lot of ships then just use a simple brute force algorithm, which will be two nested loops, i.e. O(n^2).
Keep a bitmap of the board where each bit indicates whether there's a ship occupying that tile. For each ship mark the tiles it occupies on the board, and check out if you mark the same bit twice.
(Battleship?)
Make a 2D array ("board") which contains the ID of the ship when one is present. Therefore, when you add the ship you can check in O(length) time whether a space is occupied or not.
O(n * length) time, O(N^2) space.
One way of representing a direction is as a unit vector. This can be 2 integers: dirX and dirY. Eg. dirX=1 for East; or dirY=1 for South.
You can then iterate over all positions occupied by a ship with:
int cx = x;
int cy = y;
for(int i = 0; i < length; i++) {
cx += dirX;
cy += dirY;
}
Or get a bounding-box based on these values:
x
y
x + dirX * (length - 1)
y + dirY * (length - 1)
You might want to use an enum type for your direction. In terms of finding overlaps, create a two dimensional array of booleans initialized to false for your board. Then, for each ship, finding the corresponding entries in the array and, if they are already true, you have an overlap. Otherwise, set those entries to true. If you have placed all your ships and didn't encounter an already true entry, then there is no overlap.

Resources