Can someone please explain to me why is GCD used in the following Solution:
http://www.codechef.com/viewsolution/2849602 (for c)
http://www.codechef.com/viewsolution/2849324 (for c++)
for the question: http://www.codechef.com/ACMKAN13/problems/LINEPROB
A Sniper is standing at the point (x1, y1) on the 2D XY Plane. He shoots from his position towards the point (x2, y2). You may assume that all points are integers.
Consider the 2D grid formed by integer points on the XY Plane. The position of the Sniper and the Target are lattice points in this grid. The bullet shot by the Sniper will follow a straight line trajectory from (x1, y1) to (x2, y2). The bullet goes no further than (x2, y2).
Consider the trajectory of the bullet when the Sniper is standing at (1, 1) and the Target lies at (4, 3).
Notice how the trajectory of the bullet touches 4 cells. A cell is considered touched by the trajectory if and only if the bullet will enter the cell. How many cells are touched by the trajectory of the bullet?

Input
The first line contains a single integer T, the number of test cases. Each of the following T lines contain one test case each. Each test case contains 4 integers x1, y1, x2 and y2. The integers are separated by single space characters.
Output
For each test case, output a single line, containing the number of cells touched by the trajectory of the bullet shot from (x1, y1) to (x2, y2). Remember that a cell is considered touched by the trejectory if and only if the bullet enters the cell - only touching a side is not enough.
Constraints
0 < T < 10100
0 ≤ x1, y1, x2, y2 ≤ 1000000000
Sample Input
3
0 0 3 2
0 0 2 2
0 0 1 0
Sample Output
4
2
0
The logic behind the solution is:
number of blocks the bullet traverses going along the X-axis, plus
number of blocks the bullet traverses going along the Y-axis, minus
number of blocks that got over-counted
Given the points (X1, Y1) and (X2, Y2), let A1 = abs(X1 - X2) and A2 = abs(Y1 - Y2). Then, without loss of generality, we can consider the points (0, 0) and (A1, A2).
Notice that A1 represents the number of blocks the bullet traverses along the X-axis. But, this is also the number of vertical lines touched by the bullet on the interval (0, A1] on the grid. Similarly, A2 represents the number of blocks the bullet traverses along the Y-axis, and also the number of horizontal lines touched by the bullet on the interval (0, A2].
When viewed as the number of touched lines, it is easier to see why you need to subtract some number. The number that needs to be subtracted is the number that corresponds to the touches that occur at the intersections of vertical and horizontal lines. The number of occurrences of that are counted by the GCD of A1 and A2. In particular, it occurs at the points (k * A1/GCD(A1,A2), k * A2/GCD(A1,A2)) for k in 1 .. GCD(A1,A2).
Before explaining the logic behind using gcd I want to clarify that this may not be the exact way the author of this code had thought.
First, I do not see any use of max function in that code.
Explanation:
Let's assume that the
sniper is at (0,0) and the target is at (3,3). It is clear that the trajectory of bullet will touch 2 cells.
Remarks: When sniper and target is on the line x = y or parallel to it, cells touched are one less than that of ordinate (or abscissa). (This is equal to the sum of the x and y component of distance traveled by the bullet and subtracting the GCD of the x and y component of distance traveled by the bullet.)
sniper is at (0,0) and the target is at (0,3) or (3,0). Again it is clear, by seeing the picture, that the trajectory of bullet will touch 0 cells.
Remarks: When sniper and target is on the line x or y or parallel to x or y, cells touched are one 0. (This is equal to the sum of the x and y component of distance traveled by the bullet and subtracting the GCD of the x and y component of distance traveled by the bullet.)
sniper is at (1,1) and the target is at (4,3). It is clear that the trajectory of bullet will touch 4 cells.
Remarks: In all other cases, number of cells are equal to the sum of the x and y component of distance traveled by the bullet and subtracting the GCD of the x and y component of distance traveled by the bullet.
Related
I'm trying to find if two line segments intersects in 3D space. Both segments are given by points (x1, y1, z1) and (x2, y2, z2). The following artcile describes how to do it in 2D space: https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ but I have no clue how to distinguish points orientation in 3D space (if they are clockwise or counter-clockwise). Thanks in advance.
Calculate direction vectors d1 and d2 for both segments (d1.x = x12-x11 and so on, where x11 is starting point of the first segment, x12 is ending point)
Calculate starting points difference (b.x = x21 - x11 and so on)
Find
p = (d1 x d2) (vector product)
If p is zero vector, then lines are parallel.
If lines do intersect, (b.dot.p) should be = 0 (scalar product), else these lines are skew.
Intersection point:
ip = point11 + d1 * [ (b x d2).dot.p / (p.dot.p) ]
Note that value in [] should be in range 0..1, otherwise lines intersect outside of segments.
Seems similar approach is described in wiki
I want to find a best way because all coordinates are integer values and polygons consist of horizontal and vertical lines only. I think there may be a simple and fast method to do this.
From an asymptotic complexity point of view, a rectilinear polygon is not really simpler to process than a general one: O(N) without preprocessing, and O(Log N) after O(N Log N) preprocessing (but using a complicated procedure).
For the case of no preprocessing, the procedure is simple: consider every vertical side in turn and count those that cross the horizontal half-line from the given point (+1 upward, -1 downward). The point is inside if the final count is nonzero.
The status of points on the outline is application-dependent.
For rectilinear poygons with not too large integer coordinates, you can anyway do a little better, by "compressing" them. By two independent sorts on X and Y, you can obtain a mapping from X (or Y) to integer indexes in range [0,N). This gives the shrunk polygon below, of size NxN.
Now you can embed the polygon in an image and preprocess to label the pixels as inside/outside (by seed-filling). After filling two lookup-tables for coordinate conversion, you can obtain the status of any point in constant time O(1).
This will take O(N²+M) preprocessing time and storage, where M is the range of X and Y values.
Consider any polygon, not necessary convex, formed only with horizontal and vetical lines:
Take a point (I've drawn A,B,C,D) and draw horizontal and vertical lines passing through the point.
Let's take point A. You see the horizontal line through it crosses four (vertical) segments. Note one segment is at left and the others are at right.
For point B its horizontal line crosses also four segments, but two at left and two at right.
The conditions that a point must fulfill to be inside a polygon are:
At least one segment is horizontaly crossed at left of the point.
At least one segment is horizontaly crossed at right of the point.
Both numbers of crosses left, right must be odd.
Same three conditions for vertical lines.
So, in pseudocode it goes like this:
let nL = 0, nR = 0 //left/right counters
let nA = 0, nU = 0 //above/under counters
for each segment s(sx1,sy1, sx2, sy2) in polygon
if point is on segment
return true //or false, your choice
else if segment is vertical and pointY is inside of (sy1,sy2)
if pointX > min(sx1,sx2)
nL = nL + 1
else
nR = nR + 1
else if segment is horizontal and pointX is inside of (sx1,sx2)
if pointY > min(sy1,sy2)
nU = nU + 1
else
nA = nA + 1
//Check conditions
if nL > 0 and nR > 0 and nL is odd and nR is odd
return true
if nA > 0 and nU > 0 and nA is odd and nU is odd
return true
return false
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.
I have two lines (L1, L2) in 3D.
L has the following starting and ending coordinates : P1(x1, y1, z1) and P2(x2, y2, z2).
L2 has P3(x3, y3, z3) and P2(x2, y2, z2). Notice how both L1's and L2's P2 are same: meaning they intersect at this specific point.
Now I want to find a point P(x,y,z) at any distance from P2 that line (P,P2) is perpendicular to plane on which points (P1,P2,P3) are placed.
The cross product is the way of calculating perpendicularity relative to your two lines. You need to make vectors of your line parameters, simples way would be this:
vecL1 = (x1-x2, y1-y2, z1-z2) and
vecL2 = (x3-x2, y3-y2, z3-z2)
Cross product you can google how to calculate, but in this scenario:
//Replacing the new x,y,z's with i, j, k to avoid naming confusion.
vecL3 = vecL1 x vecL2 = (j1*k2 - j2*k1, k1*i2 - k2*i1, i1*j2 - j1*i2)
Now the cross product per definition is a new vector (line) that is strictly perpendicular to the two lines/vectors you used to calculate this with. But vectors lack position, so you need to add the intersection point to this vector in order to find some point.
//i3, j3, k3 being the third vector's parameters
P3(i3+x2, j3+y2, k3+z2)
PS: The distance from your P2 to P3 is per definition (how cross products work) to the area of a parallelogram that the two lines are sides of, I found a link to illustrate:
Normalizing the 3rd vector will make the distance equal to 1 from P2.
The cross product will give you a perpendicular vector to the plane described by two other vectors, in pseudo-code:
normal = cross(normalize(P1-P2), normalize(P3-P2))
Since you've defined P2 as the point of intersection, you can simply add this normal vector to P2 to get your perpendicular point.
If you have any line AB then an arbitrary point C will always be perpendicular to AB IFF triangle ABC has no angle larger than π/2
That means there will always be a point D on line AB such that CD is perpendicular to AB
I calculated the histogram(a simple 1d array) for an 3D grayscale Image.
Now I would like to calculate the gradient for the this histogram at each point. So this would actually mean I have to calculate the gradient for a 1D function at certain points. However I do not have a function. So how can I calculate it with concrete x and y values?
For the sake of simplicity could you probably explain this to me on an example histogram - for example with the following values (x is the intensity, and y the frequency of this intensity):
x1 = 1; y1 = 3
x2 = 2; y2 = 6
x3 = 3; y3 = 8
x4 = 4; y4 = 5
x5 = 5; y5 = 9
x6 = 6; y6 = 12
x7 = 7; y7 = 5
x8 = 8; y8 = 3
x9 = 9; y9 = 5
x10 = 10; y10 = 2
I know that this is also a math problem, but since I need to solve it in c++ I though you could help me here.
Thank you for your advice
Marc
I think you can calculate your gradient using the same approach used in image border detection (which is a gradient calculus). If your histogram is in a vector you can calculate an approximation of the gradient as*:
for each point in the histogram compute
gradient[x] = (hist[x+1] - hist[x])
This is a very simple way to do it, but I'm not sure if is the most accurate.
approximation because you are working with discrete data instead of continuous
Edited:
Other operators will may emphasize small differences (small gradients will became more emphasized). Roberts algorithm derives from the derivative calculus:
lim delta -> 0 = f(x + delta) - f(x) / delta
delta tends infinitely to 0 (in order to avoid 0 division) but is never zero. As in computer's memory this is impossible, the smallest we can get of delta is 1 (because 1 is the smallest distance from to points in an image (or histogram)).
Substituting
lim delta -> 0 to lim delta -> 1
we get
f(x + 1) - f(x) / 1 = f(x + 1) - f(x) => vet[x+1] - vet[x]
Two generally approaches here:
a discrete approximation to the derivative
take the real derivative of a fitted function
In the first case try:
g = (y_(i+1) - y_(i-1))/2*dx
at all the points except the ends, or one of
g_left-end = (y_(i+1) - y_i)/dx
g_right-end = (y_i - y_(i-1))/dx
where dx is the spacing between x points. (Unlike the equally correct definition Andres suggested, this one is symmetric. Whether it matters or not depends on you use case.)
In the second case, fit a spline to your data[*], and ask the spline library the derivative at the point you want.
[*] Use a library! Do not implement this yourself unless this is a learning project. I'd use ROOT because I already have it on my machine, but it is a pretty heavy package just to get a spline...
Finally, if you data is noisy, you ma want to smooth it before doing slope detection. That was you avoid chasing the noise, and only look at large scale slopes.
Take some squared paper and draw on it your histogram. Draw also vertical and horizontal axes through the 0,0 point of your histogram.
Take a straight edge and, at each point you are interested in, rotate the straight edge until it accords with your idea of what the gradient at that point is. It is most important that you do this, your definition of gradient is the one you want.
Once the straight edge is at the angle you desire draw a line at that angle.
Drop perpendiculars from any 2 points on the line you just drew. It will be easier to take the following step if the horizontal distance between the 2 points you choose is about 25% or more of the width of your histogram. From the same 2 points draw horizontal lines to intersect the vertical axis of your histogram.
Your lines now define an x-distance and a y-distance, ie the length of the horizontal/ vertical (respectively) axes marked out by their intersections with the perpendiculars/horizontal lines. The gradient you want is the y-distance divided by the x-distance.
Now, to translate this into code is very straightforward, apart from step 2. You have to define what the criteria are for determining what the gradient at any point on the histogram is. Simple choices include:
a) at each point, set down your straight edge to pass through the point and the next one to its right;
b) at each point, set down your straight edge to pass through the point and the next one to its left;
c) at each point, set down your straight edge to pass through the point to the left and the point to the right.
You may want to investigate more complex choices such as fitting a curve (such as a quadratic or higher-order polynomial) through a number of points on your histogram and using the derivative of that to represent the gradient.
Until you understand the question on paper avoid coding in C++ or anything else. Once you do understand it, coding should be trivial.