If I am given 100 points in the coordinate system, and I have to find if there exist a right angled triangle in those vertices.
Is there a way that I can detect the right angled triangle among those vertices without having to choose all pairs of 3 vertices and then applying Pythagoras theorem on them??
Can there be a better algorithm for this?
Thanks for any help. :)
Here's an O(n^2 log n)-time algorithm for two dimensions only. I'll describe what goes wrong in higher dimensions.
Let S be the set of points, which have integer coordinates. For each point o in S, construct the set of nonzero vectors V(o) = {p - o | p in S - {o}} and test whether V(o) contains two orthogonal vectors in linear time as follows.
Method 1: canonize each vector (x, y) to (x/gcd(x, y), y/gcd(x, y)), where |gcd(x, y)| is the largest integer that divides both x and y, and where gcd(x, y) is negative if y is negative, positive if y is positive, and |x| if y is zero. (This is very similar to putting a fraction in lowest terms.) The key fact about two dimensions is that, for each nonzero vector, there exists exactly one canonical vector orthogonal to that vector, specifically, the canonization of (-y, x). Insert the canonization of each vector in V(o) into a set data structure and then, for each vector in V(o), look up its canonical orthogonal mate in that data structure. I'm assuming that the gcd and/or set operations take time O(log n).
Method 2: define a comparator on vectors as follows. Given vectors (a, b), (c, d), write (a, b) < (c, d) if and only if
s1 s2 (a d - b c) < 0,
where
s1 = -1 if b < 0 or (b == 0 and a < 0)
1 otherwise
s2 = -1 if d < 0 or (d == 0 and c < 0)
1 otherwise.
Sort the vectors using this comparator. (This is very similar to comparing the fraction a/b with c/d.) For each vector (x, y) in V(o), binary search for its orthogonal mate (-y, x).
In three dimensions, the set of vectors orthogonal to the unit vector along the z-axis is the entire x-y-plane, and the equivalent of canonization fails to map all vectors in this plane to one orthogonal mate.
Related
We know that degenerate triangle is a triangle which has all three of its points in a line, and thus has all of its sides on top of each other. So there is a three sides of triangle and now I have to determine whether it degenerate triangle or generate triangle.
How can I proceed to solve this using C language ?
When you have three side lengths satisfying a ≤ b ≤ c and the sum a + b = c, then the triangle is degenerate.
(Valid triangles have a + b > c and triangles with a + b < c are not possible.)
If a, b, and c are the lengths of the three sides of a triangle, then
a + b > c
a + c > b
b + c > a
If any one of these inequalities is not true, then we get a degenerate triangle.
In simple term,first sort the a, b, c in ascending order then check below condition
a + b <= c
if this condition satisfy then triangle is degenerate triangle.
You need to figure out if points A, B and C are on the same line. If AB and AC have the same slope then they are colinear (on the same line).
You've now reduced the problem to calculating slope which should be easy in C.
Given the side lengths a,b,c of the triangle, you can calculate the triangle's area via Heron's formula. If the area is 0 (or smaller than a given threshold, b/c of roundoff errors), then the triangle is degenerate.
Given the triangle's vertices A,B,C, you can calculate the area of the parallelogram spanned by (A-B) and (B-C) by taking their cross product's magnitude. If this area is zero, your triangle is degenerate. Also you can equivalently calculate the side lengths from the vertices and go back to using Heron's formula.
Given two discrete random variables, their (arbitrary) probability mass functions a and b and a natural-number N such that both of the variables have the domain [0..N] (therefore the functions can be represented as arrays), the probability that the functions' corresponding random variables have a given sum (i.e. P(A+B==target)) can be computed, in O(N) time, by treating the arrays as vectors and using their dot product, albeit with one of the inputs reversed and both inputs re-sliced in order to align them and eliminate bounds errors; thus each position i of a is matched with a position j of b such that i+j==target. Such an algorithm looks something like this:
-- same runtime as dotProduct and sum; other components are O(1)
P :: Vector Int -> Vector Int -> Int -> Ratio Int
P a b target | length a /= length b = undefined
| 0 <= target && target <= 2 * length a
= (dotProduct (shift target a) (reverse (shift target b)))
%
(sum a * sum b) -- O(length a)
-- == sum $ map (\x -> (a!x)*(b!(target-x))) [0..length a]
| otherwise = 0
where
-- O(1)
shift t v = slice start' len' v
where start = t - length v - 1
len = length v - abs start
-- unlike `drop ... $ take ... v`,
-- slice does not simply `id` when given out-of-bounds indices
start' = min (V.length v) (max 0 start)
len' = min (V.length v) (max 0 len)
-- usual linear-algebra definition
-- O(length a); length inequality already guarded-away by caller
dotProduct a b = sum $ zipWith (*) a b
Given the same information, one might treat the variables' sum as its own discrete random variable, albeit one whose probability mass function is unknown. Evaluating the entirety of this probability mass function (and thereby producing the array that corresponds thereto) can be done in O(N²) time by performing N dot-products, with each product having its operands differently-shifted; i.e.:
pm :: Vector Int -> Vector Int -> Vector (Ratio Int)
pm a b = map (P a b) $ generate (2 * length a + 1) id
I am told, however, that producing such a table of values of this probability mass function can actually be done in O(N*log(N)) time. As far as I can tell, no two of the multiplications across all of the involved dot-products share the same ordered pair of indices, and I do not think that I can, e.g., combine two dot-subproducts in any useful way to form a T(n)=2T(n/2)+O(n)-type recursion; therefore I am curious as to how and why, exactly, such a runtime is possible.
In a nutshell, you have a transformation F (called discrete Fourier transform) that maps the set of vectors of size N onto itself and such that
F(a*b) = F(a).F(b)
where * is the convolution operator you just described and . is the standard dot product.
Moreover Fis invertible and you can therefore recover a*b as
a*b = F^{-1}(F(a).F(b))
Now this is all very nice but the key point is that F (and F^{-1}) can be computed in O(N log(N)) time using something called Fast Fourier Transform (FFT). Thereby, because the usual dot product . can be computed in O(N), you obtain a O(N log(N)) algorithm for computing the convolution of two distributions.
I therefore suggest you look up this and that.
I have a connected directed weighted graph. The edge weights represent probabilities of moving between vertices; weights for all edges emanating from a vertex sum up to one. The graph contains two sinks: A and B. For each vertex in the graph, I want to know the probability that a walk originating there will reach A and the same for B. What kind of problem is this? How do I solve it?
This problem is of the algebra kind. For a path starting at a vertex, the probability of reaching A is the average of probabilities of reaching A from each of its neighbouring vertices, weighted by the edge weights. Let's put this into more concrete terms.
Let P be the adjacency matrix for the graph. That is, Pi,j is the probability of moving from vertex i to vertex j. Set PA,A = 1. If we take a vector of probabilities assigned to each vertex and multiply it by P, then the resulting vector contains a weighted average of each vertex's neighbours. What we are looking for is a vector v, such that P v = v and vA = 1.
This vector v is the eigenvector of P corresponding to the eigenvalue of 1. Does P always have such an eigenvalue? Fortunately, the Perron-Frobenius theorem tells us that it does, and that this is the largest eigenvalue of P. The solution is then to form the adjacency matrix P and find the eigenvector corresponding to its largest eigenvalue.
There is also an approximate solution. If we take a vector x of vertex probabilities, with xA = 1, and the other elements set to 0, then Pk x will converge to v as k goes to infinity. Pk might be easier to compute for small values of k than the eigenvector.
Example
Let's look at the following simple graph:
If we order the vertices alphabetically, then the matrix P corresponding to the graph is:
This matrix has an eigenvalue equal to 1, and the corresponding eigenvector is: [1 0 70/79 49/79]. That is, the exact probability of reaching A from C is 70/79, and from D it is 49/79. If you work out the answer for B, it comes out to 9/79 and 30/79, which is exactly what we expect.
The value of P16 [1 0 0 0] is approximately [1 0 0.886 0.62] and is correct to 6 decimal places.
I am looking for a fast algorithm:
I have a int array of size n, the goal is to find all patterns in the array that
x1, x2, x3 are different elements in the array, such that x1+x2 = x3
For example I know there's a int array of size 3 is [1, 2, 3] then there's only one possibility: 1+2 = 3 (consider 1+2 = 2+1)
I am thinking about implementing Pairs and Hashmaps to make the algorithm fast. (the fastest one I got now is still O(n^2))
Please share your idea for this problem, thank you
Edit: The answer below applies to a version of this problem in which you only want one triplet that adds up like that. When you want all of them, since there are potentially at least O(n^2) possible outputs (as pointed out by ex0du5), and even O(n^3) in pathological cases of repeated elements, you're not going to beat the simple O(n^2) algorithm based on hashing (mapping from a value to the list of indices with that value).
This is basically the 3SUM problem. Without potentially unboundedly large elements, the best known algorithms are approximately O(n^2), but we've only proved that it can't be faster than O(n lg n) for most models of computation.
If the integer elements lie in the range [u, v], you can do a slightly different version of this in O(n + (v-u) lg (v-u)) with an FFT. I'm going to describe a process to transform this problem into that one, solve it there, and then figure out the answer to your problem based on this transformation.
The problem that I know how to solve with FFT is to find a length-3 arithmetic sequence in an array: that is, a sequence a, b, c with c - b = b - a, or equivalently, a + c = 2b.
Unfortunately, the last step of the transformation back isn't as fast as I'd like, but I'll talk about that when we get there.
Let's call your original array X, which contains integers x_1, ..., x_n. We want to find indices i, j, k such that x_i + x_j = x_k.
Find the minimum u and maximum v of X in O(n) time. Let u' be min(u, u*2) and v' be max(v, v*2).
Construct a binary array (bitstring) Z of length v' - u' + 1; Z[i] will be true if either X or its double [x_1*2, ..., x_n*2] contains u' + i. This is O(n) to initialize; just walk over each element of X and set the two corresponding elements of Z.
As we're building this array, we can save the indices of any duplicates we find into an auxiliary list Y. Once Z is complete, we just check for 2 * x_i for each x_i in Y. If any are present, we're done; otherwise the duplicates are irrelevant, and we can forget about Y. (The only situation slightly more complicated is if 0 is repeated; then we need three distinct copies of it to get a solution.)
Now, a solution to your problem, i.e. x_i + x_j = x_k, will appear in Z as three evenly-spaced ones, since some simple algebraic manipulations give us 2*x_j - x_k = x_k - 2*x_i. Note that the elements on the ends are our special doubled entries (from 2X) and the one in the middle is a regular entry (from X).
Consider Z as a representation of a polynomial p, where the coefficient for the term of degree i is Z[i]. If X is [1, 2, 3, 5], then Z is 1111110001 (because we have 1, 2, 3, 4, 5, 6, and 10); p is then 1 + x + x2 + x3 + x4 + x5 + x9.
Now, remember from high school algebra that the coefficient of xc in the product of two polynomials is the sum over all a, b with a + b = c of the first polynomial's coefficient for xa times the second's coefficient for xb. So, if we consider q = p2, the coefficient of x2j (for a j with Z[j] = 1) will be the sum over all i of Z[i] * Z[2*j - i]. But since Z is binary, that's exactly the number of triplets i,j,k which are evenly-spaced ones in Z. Note that (j, j, j) is always such a triplet, so we only care about ones with values > 1.
We can then use a Fast Fourier Transform to find p2 in O(|Z| log |Z|) time, where |Z| is v' - u' + 1. We get out another array of coefficients; call it W.
Loop over each x_k in X. (Recall that our desired evenly-spaced ones are all centered on an element of X, not 2*X.) If the corresponding W for twice this element, i.e. W[2*(x_k - u')], is 1, we know it's not the center of any nontrivial progressions and we can skip it. (As argued before, it should only be a positive integer.)
Otherwise, it might be the center of a progression that we want (so we need to find i and j). But, unfortunately, it might also be the center of a progression that doesn't have our desired form. So we need to check. Loop over the other elements x_i of X, and check if there's a triple with 2*x_i, x_k, 2*x_j for some j (by checking Z[2*(x_k - x_j) - u']). If so, we have an answer; if we make it through all of X without a hit, then the FFT found only spurious answers, and we have to check another element of W.
This last step is therefore O(n * 1 + (number of x_k with W[2*(x_k - u')] > 1 that aren't actually solutions)), which is maybe possibly O(n^2), which is obviously not okay. There should be a way to avoid generating these spurious answers in the output W; if we knew that any appropriate W coefficient definitely had an answer, this last step would be O(n) and all would be well.
I think it's possible to use a somewhat different polynomial to do this, but I haven't gotten it to actually work. I'll think about it some more....
Partially based on this answer.
It has to be at least O(n^2) as there are n(n-1)/2 different sums possible to check for other members. You have to compute all those, because any pair summed may be any other member (start with one example and permute all the elements to convince yourself that all must be checked). Or look at fibonacci for something concrete.
So calculating that and looking up members in a hash table gives amortised O(n^2). Or use an ordered tree if you need best worst-case.
You essentially need to find all the different sums of value pairs so I don't think you're going to do any better than O(n2). But you can optimize by sorting the list and reducing duplicate values, then only pairing a value with anything equal or greater, and stopping when the sum exceeds the maximum value in the list.
I'm looking for tips or research papers that will help me perform the sum (i=0 to k) of X^i * Y, or more explicitly, Y + X^1 * Y +...+ X^k * Y in CUDA C. Where X is an N-by-N matrix, and Y is a N-by-1 vector
You should check out Thrust.
Factor out the Y, then just do a scan (using multiplication as the operator) followed by a reduction (using addition as the operator).
I know this isn't what you're looking for, but can't you factor the Y out and just right multiply it with the result of sum(i=0 to k) of X^i?
Besides factoring out Y from the summation, you could compute the eigenspace of X and subsequently very efficiently compute each X^i (the slowest part of computing your summation will undoubtedly be raising X to a range of powers, so I'll attack that).
More specifically, compute the eigenvalues of X and form a diagonal matrix of the eigenvalues, call this Q. Using the eigenvalues, we can diagonalize X and create a new matrix D such that
(1) D = Q^-1 X Q
Because D is diagonal, we can very efficiently compute it raised to any power i. Applying (1) we determine that
(2) D^i = (Q^-1 X Q)^i
and furthermore, we can show that (2) is equivalent to
(3) D^i = Q^-1 X^i Q
Finally, we can find any arbitrary X^i efficiently by rearranging our equation and computing
(4) X^i = Q D^i Q^-1
(I wanted to verify my memory here, so I found a reference on Wikipedia).