I am trying to solve this math concept programmatically. Given two points A and B, on a rounded grid, find the points along the line from A to B that intersect with the rounded grid. I have looked into fast voxel traversal algorithms but they do not seem to only get points that are on the grid, instead just any points that intersect.
Here is a picture that might better describe my problem:
I am given the two orange points on any line, but I want to be able to find the blue points that that line intersects with. As you can see, the blue points are rounded to the grid.
Let me know if I can clarify anything.
There's two points that we know will always be aligned with the grid: the points at the end of the segment. I'll call them a and b. The vector describing the segment is then b - a (v).
v can be reduced while maintaining the ratio of the vector as follows:
v' = v / gcd(v_x, v_y)
where v_x and v_y are the x and y-components of v respectively. v' is the smallest possible vector with the same orientation as v consisting solely of integer components. This means that a + v' * n will be aligned to the grid for any n we may pick.
So the points on the line that are grid-aligned would be [a + 0 * v', a + 1 * v', ..., a + m * v'], where a + m * v' = b must hold. So we need to solve
a_x + m * v'_x = b_x
a_y + m * v'_y = b_y
which lead to
m = (b_x - a_x) / v'_x
m = (b_y - a_y) / v'_y
However there are three possible edge-cases to consider here:
a == b: none of the equations are solveable (and there's exactly one grid-aligned point anyways)
v'_x == 0 or v'_y == 0: just pick the other equation to find m
Putting it all together as pythonesque pseudocode:
grid_aligned(a, b):
if a == b:
return [a]
v = b - a
v' = v / gcd(v.x, v.y)
if v'.x == 0:
m = v.y / v'.y
else:
m = v.x / v'.x
return [a + v' * n for n in 0..m]
The task is to find the amount of distinct pairs of {x, y} that fits the equation 1/x + 1/y = 1/n, with n being the input given by the user. Different ordering of x and y does not count as a new pair.
For example, the value n = 2 will mean 1/n = 1/2. 1/2 can be formed with two pairs of {x, y}, whcih are 6 and 3 and 4 and 4.
The value n = 3 will mean 1/n = 1/3. 1/3 can be formed with two pairs of {x, y}, which are 4 and 12 and 6 and 6.
The mathematical equation of 1/x + 1/y = 1/n can be converted to y = nx/(x-n) where if y and x in said converted equation are whole, they count as a pair of {x, y}. Using said converted formula, I will iterate n times starting from x = n + 1 and adding x by 1 per iteration to find whether nx % (x - n) == 0; if it yields true, the x and y are a new distinct pair.
I found the answer to limit my iteration by n times by manually computing the answers and finding the number of repetitions 'pattern'. x also starts with n+1 because otherwise, division by zero will happen or y will result in a negative number. The modulo operator is to indicate that the y attained is whole.
Questions:
Is there a mathematical explanation behind why the iteration is limited to n times? I found out that the limit of iteration is n times by doing manual computation and finding the pattern: that I only need to iterate n times to find the amount of distinct pairs.
Is there another way to find the amount of distinct pairs {x, y} other than my method above, which is by finding the VALUES of distinct pairs itself and then summing the amount of distinct pair? Is there a quick mathematical formula I'm not aware of?
For reference, my code can be seen here: https://gist.github.com/TakeNoteIAmHere/596eaa2ccf5815fe9bbc20172dce7a63
Assuming that x,y,n > 0 we have
Observation 1: both, x and y must be greater than n
Observation 2: since (x,y) and (y,x) do not count as distinct, we can assume that x <= y.
Observation 3: x = y = 2n is always a solution and if x > 2n then y < x (thus no new solution)
This means the possible values for x are from n+1 up to 2n.
A little algebra convers the equation
1/x + 1/y = n
into
(x-n)*(y-n) = n*n
Since we want a solution in integers, we seek integers f, g so that
f*g = n*n
and then the solution for x and y is
x = f+n, y = g+n
I think the easiest way to proceed is to factorise n, ie write
n = (P[1]^k[1]) * .. *(P[m]^k[m])
where the Ps are distinct primes, the ks positive integers and ^ denotes exponentiation.
Then the possibilities for f and g are
f = P[1]^a[1]) * .. *(P[m]^a[m])
g = P[1]^b[1]) * .. *(P[m]^b[m])
where the as and bs satisfy, for each i=1..m
0<=a[i]<=2*k[i]
b[i] = 2*k[i] - a[i]
If we just wanted to count the number of solutions, we would just need to count the number of fs, ie the number of distinct sequences a[]. But this is just
Nall = (2*k[1]+1)*... (2*[k[m]+1)
However we want to count the solution (f,g) and (g,f) as being the same. There is only one case where f = g (because the factorisation into primes is unique, we can only have f=g if the a[] equal the b[]) and so the number we seek is
1 + (Nall-1)/2
I have a single large rectangle of dimensions L*W, and n smaller rectangles that each have the same dimension l * w. Every small rectangle has the same dimensions.
My goal is to fit all n of smaller rectangles into the large rectangle while making the most efficient use of space in the large rectangle possible. l and w can be scaled up or down as needed, as long as the proportion is kept the same.
How can it be determined how the smaller rectangles should be scaled to fit them all in the large rectangle?
Here is an algorithm that finds the max value of a scaling factor F such that all small a x b rectangles, when scaling by F will fit in the containing rectangle A x B:
For every pair (p, q) of positive integers such that
p <= n
q <= n
n = p * q - r for some integer r >= 0 satisfying r < p or p < q
compute f = min(A/(a*p), B/(b*q)).
Let F be the maximum of all factors f computed in 1.
The computation of all pairs (p, q) may proceed as follows:
[Initialize] p := 0
[Increment] p := p + 1
[End?] If p > n, stop
[Next] Let q := n + p - 1 / p (integer division). Next pair (p, q).
[Repeat] Go to 2.
Idea of the algorithm
Every pair (p, q) represents a particular layout of the scaled rectangles with p rectangles in an horizontal row and q rows, the last one possibly incomplete. Here is an example for n = 13 written as 3 * 5 - 2:
Since p scaled rectangles of width f*a must fit in a rectangle of width A, we have: p*f*a <= A or f <= A/(p*a). Similarly f <= B/(q*b). Therefore the maximum scale for this configuration is min(A/(p*a), B/(q*b)).
I am solving a competitive programming problem, it was described like this:
Given n < 10^5 integer a1, a2, a3, ..., an and L, R. How many
subarrays are there such that sum of its element in range [L, R].
Example:
Input:
n = 4, L = 2, R = 4
1 2 3 4
Output: 4
(4 = 4, 3 = 1 + 2 = 3, 2 = 2)
One solution I have is bruteforce, but O(n^2) is too slow. What data structures / algorithms should I use to solve this problem efficiently ?
Compute prefix sums(p[0] = 0, p[1] = a1, p[2] = a1 + a2, ..., p[n] = sum of all numbers).
For a fixed prefix sum p[i], you need to find the number of such prefix sums p[j] that j is less than i and p[i] - R <= p[j] <= p[i] - L. One can do it in O(log n) with treap or another balanced binary search tree.
Pseudo code:
treap.add(0)
sum = 0
ans = 0
for i from 1 to n:
sum += a[i]
left, right = treap.split(sum - R)
middle, right = right.split(sum - L)
ans += middle.size()
merge left, middle and right together
treap.add(sum)
We can do it in linear time if the array contains positive numbers only.
First build an array with prefix sum from left to right.
1. Fix three pointers, X, Y and Z and initialize them with 0
2. At every step increase X by 1
3. While sum of numbers between X and Y are greater than R keep increasing Y
4. While sum of numbers between X and Z are greater than or equal to L, keep increasing Z
5. If valid Y and Z are found, add Z - Y + 1 to result.
6. If X is less than length of the array, Go to step 2.
I already have prime factorization (for integers), but now I want to implement it for gaussian integers but how should I do it? thanks!
This turned out to be a bit verbose, but I hope it fully answers your question...
A Gaussian integer is a complex number of the form
G = a+bi
where i2 = -1, and a and b are integers.
The Gaussian integers form a unique factorization domain. Some of them act as units (e.g. 1, -1, i, and -i), some as primes (e.g. 1 + i), and the rest composite, that can be decomposed as a product of primes and units that is unique, aside from the order of factors and the presence of a set of units whose product is 1.
The norm of such a number G is defined as an integer: norm(G) = a2 + b2 .
It can be shown that the norm is a multiplicative property, that is:
norm(I*J) = norm(I)*norm(J)
So if you want to factor a Gaussian integer G, you could take advantage of the fact that any Gaussian integer I that divides G must satisfy the property that norm(I) divides norm(G), and you know how to find the factors of norm(G).
The primes of the Gaussian integers fall into three categories:
1 +/- i , with norm 2,
a +/- bi, with prime norm a2+b2 congruent to 1 mod 4 ,
a, where a is a prime congruent to 3 mod 4 , with norm a2
Now to turn this into an algorithm...if you want to factor a Gaussian integer G,
you can find its norm N, and then factor that into prime integers. Then
we work our way down this list, peeling off prime factors p of N that correspond
to prime Gaussian factors q of our original number G.
There are only three cases to consider, and two of them are trivial.
If p = 2, let q = (1+i). (Note that q = (1-i) would work equally well, since they only differ by a unit factor.)
If p = 3 mod 4, q = p. But the norm of q is p2, so we can strike
another factor of p from the list of remaining factors of norm(G).
The p = 1 mod 4 case is the only one that's a little tricky to deal with.
It's equivalent to the problem of expressing p as the sum of two squares:
if p = a2 + b2, then a+bi and a-bi form a conjugate pair of Gaussian
primes with norm p, and one of them will be the factor we're looking for.
But with a little number theory, it turns out not to be too difficult.
Consider the integers mod p. Suppose we can find an integer k such
that k2 = -1 mod p. Then k2+1 = 0 mod p, which is equivalent to
saying that p divides k2+1 in the integers (and therefore also the
Gaussian integers). In the Gaussian integers, k2+1 factors into
(k+i)(k-i). p divides the product, but does not divide either
factor. Therefore, p has a nontrivial GCD with each of the
factors (k+i) and (k-i), and that GCD or its conjugate is the
factor we're looking for!
But how do we find such an integer k? Let n be some integer between
2 and p-1 inclusive. Calculate n(p-1)/2 mod p -- this value will be either
1 or -1. If -1, then k = n(p-1)/4, otherwise try a different n.
Nearly half the possible values of n will give us a square root of
-1 mod p, so it won't take many guesses to find a value of k that
works.
To find the Gaussian primes with norm p, just use Euclid's algorithm
(slightly modified to work with Gaussian integers) to compute the GCD
of (p, k+i). That gives one trial divisor. If it evenly divides the
Gaussian integer we're trying to factor (remainder = 0), we're done.
Otherwise, its conjugate is the desired factor.
Euclid's GCD algorithm for Gaussian integers is almost identical to
that for normal integers. Each iteration consists of a trial division
with remainder. If we're looking for gcd(a,b),
q = floor(a/b), remainder = a - q*b, and if the remainder is nonzero
we return gcd(b,remainder).
In the integers, if we get a fraction as the quotient, we round it toward zero.
In the Gaussian integers, if the real or imaginary parts of the quotient are fractions, they get rounded to the nearest integer. Besides that, the
algorithms are identical.
So the algorithm for factoring a Gaussian integer G looks something like
this:
Calculate norm(G), then factor norm(G) into primes p1, p2 ... pn.
For each remaining factor p:
if p=2, u = (1 + i).
strike p from the list of remaining primes.
else if p mod 4 = 3, q = p, and strike 2 copies of p from the list of primes.
else find k such that k^2 = -1 mod p, then u = gcd(p, k+i)
if G/u has remainder 0, q = u
else q = conjugate(u)
strike p from the list of remaining primes.
Add q to the list of Gaussian factors.
Replace G with G/q.
endfor
At the end of this procedure, G is a unit with norm 1. But it's not necessarily
1 -- it could be -1, i, or -i, in which case add G to the list of factors,
to make the signs come out right when you multiply all the factors to
see if the product matches the original value of G.
Here's a worked example: factor G = 361 - 1767i over the Gaussian integers.
norm(G) = 3252610 = 2 * 5 * 17 * 19 * 19 * 53
Considering 2, we try q = (1+i), and find G/q = -703 - 1064i with remainder 0.
G <= G/q = -703 - 1064i
Considering 5, we see it is congruent to 1 mod 4. We need to find a good k.
Trying n=2, n(p-1)/2 mod p = 22 mod p = 4. 4 is congruent to -1 mod 5. Success! k = 21 = 2. u = gcd(5, 2+i) which works out to be 2+i.
G/u = -494 - 285i, with remainder 0, so we find q = 2+i.
G <= G/q = -494 - 285i
Considering 17, it is also congruent to 1 mod 4, so we need to find another
k mod 17. Trying n=2, 28 = 1 mod 17, no good. Try n=3 instead.
38 = 16 mod 17 = -1 mod 17. Success! So k = 34 = 13 mod 17.
gcd(17, 13+i) = u = 4-i, G/u = -99 -96i with remainder -2. No good,
so try conjugate(u) = 4+i. G/u = -133 - 38i with remainder 0. Another factor!
G <= G/(4+i) = -133 - 38i
Considering 19, it is congruent to 3 mod 4. So our next factor is 19, and
we strike the second copy of 19 from the list.
G <= G/19 = -7 - 2i
Considering 53, it is congruent to 1 mod 4. Again with the k process...
Trying n=2, 226 = 52 mod 53 = -1 mod 53. Then k = 213 mod 53 = 30.
gcd(53,30+i) = u = -7 - 2i. That's identical to G, so the final
quotient G/(-7-2i) = 1, and there are no factors of -1, i, or -i to worry
about.
We have found factors (1+i)(2+i)(4+i)(19+0i)(-7-2i). And if you multiply
that out (left as an exercise for the reader...), lo and behold, the
product is 361-1767i, which is the number we started with.
Ain't number theory sweet?
Use floating point for the real and imaginary components if you want full single cell integer accuracy, and define gsub, gmul and a special division gdivr with rounded coefficients, not floored. That's because the Pollard rho factorization method needs gcd via Euclid's algorithm, whith a slightly modified gmodulo:
gmodulo((x,y),(x',y'))=gsub((x,y),gmul((x',y'),gdivr((x,y),(x',y'))))
Pollard rho
def poly((a,b),(x,y))=gmodulo(gsub(gmul((a,b),(a,b)),(1,0)),(x,y))
input (x,y),(a,b) % (x,y) is the Gaussian number to be factorized
(c,d)<-(a,b)
do
(a,b)=poly((a,b),(x,y))
(c,d)=poly(poly((c,d),(x,y)),(x,y))
(e,f)=ggcd((x,y),gsub((a,b),(c,d)))
if (e,f)=(x,y) then return (x,y) % failure, try other (a,b)
until e^2+f^2>1
return (e,f)
A normal start value is a=1, b=0.
I have used this method programmed in Forth on my blog http://forthmath.blogspot.se
For safety, use rounded values in all calculations while using floating points for integers.