What are the different versions of arithmetic swap and why do they work? - math

I think we all should be familiar of the arithmetic swap algorithm, that swaps two variables without using a third variable. Now I found out that there are two variations of the arithmetic swap. Please consider the following:
Variation 1.
int a = 2;
int b = 3;
a = a + b;
b = a - b;
a = a - b;
Variation 2.
int a = 2;
int b = 3;
b = b - a;
a = a + b;
b = a - b;
I want to know, why are there two distinct variations of the arithmetic swap and why do they work? Are there also other variations of the arithmetic swap that achieve the same result? How are they related? Is there any elegant mathematical formula that justifies why the arithmetic swap works the way it does, for all variations? Is there anything related between these two variations of the two arithmetic swap, like an underlying truth?

Break each variable out as what it represents:
a = 2
b = 3
a1 = a + b
b1 = a1 - b = (a + b) - b = a
a2 = a1 - b1 = (a + b) - a = b
a = 2
b = 3
b1 = b - a
a1 = a + b1 = a + (b - a) = b
b2 = a1 - b1 = b - (b - a) = a
There's not underlying truth other than the fact that the math works out. Remember that each time you do an assignment, it's effectively a new "variable" from the math side.

Related

Is there a way to prove that this example of a hascode algorithm will give unique values

I was watching https://www.youtube.com/watch?v=UPo-M8bzRrc&index=21&list=PL4BBB74C7D2A1049C,(CS 61B Lecture 21: Hash Tables) and the example the professor gave was
You have a two letter word, each letter falls between a-z
public class Word{
public static final int LETTERS = 26, WORDS = LETTERS * LETTERS;
private String word;
public int hashCode(){
return LETTERS * (word.charAt(0)-'a') + word.charAt(1) - 'a';
}
}
Is there a way to prove(mathematical?) that each possible word will map to a different value between 0 and 675?
I've proved that the range will be between 0 and 675(give "aa" and "zz", but unsure about how to prove uniqueness.
The formula to get the hash code is:
hash = 26 * (A - 'a') + (B - 'a')
= 26 * (A - 97) + (B - 97) // 'a' == 97 in ASCII
= 26A + B - 27*97
So what we need to prove is that 26A + B has distinct values for any A and B in range <97; 122> (decimal values for <'a'; 'z'>). We ignore the constant `27 * 97 part, as it would not change the reasoning.
Let's look at the opposite statement - when the hash code would not be distinct? It would not be distinct when change in A would be compensated by the change in B. So the following would need to be true:
26 * A1 + B1 = 26 * A2 + B2
Let's assume that A2 = A1 + 1:
26 * A1 + B1 = 26 * (A1 + 1) + B2
= 26 * A1 + B2 + 26
Which means:
B1 = B2 + 26
B1 - B2 = 26
Which is impossible, because B is the char code for letters in range <'a'; 'z'>. And this range, in decimal ASCII values, is 25 (122-97). The required compensation by B would increase for every other A1 - A2 difference.
So, by proving the opposite is impossible, we've proved that hash code is unique for that characters.

Finding number of Pythagorean triples within a given range

I am trying to write a program which prints Pythagorean triples (a^2 + b^2 = c^2) for a given range N where a<=b<=c<=N.
#include <stdio.h>
int main()
{
int a = 0, b = 0, c = 0, N, T,c2;
scanf("%d", &T);
while(T--)
{
int counter = 0;
scanf("%d", &N);
{
for (c = 0; c <=N; c++)
{
for (b = 0; b < c; b++)
{
for (a = 0; a < b; a++)
{
c2 = c*c;
if (a*a + b*b == c2 )
//if(sqrt (pow(a,2) + pow(b,2)) == c)
{
++counter;
printf("\n %d , %d, %d \n",a,b,c); }
}
}
}
}
printf("%d\n", counter);
}
return 0;
}
This works well for N<1000. For higher N, say 10000 this takes a lot of time.
Is there any better way to optimize this prog or any better algorithm instead of brute force, so that it takes less time to compute for higher N ?
By number theory, Pythagorean triples are parametrized by (2pq, p^2-q^2, p^2+q^2). You can enumerate over these and just abort whenever c > N. This is of course optimal since you do as many computations as there are triples...
First, you can compute c2 as soon as a new value of c is available:
for (c = 0; c <=N; c++)
{
/* compute c2 here */
This saves the time to compute it over and over for each b and a.
The same goes for b: it is possible to compute the square of b as soon as b is available, instead of for each value of a. Your compiler may automatically apply these optimizations, but not necessarily.
Lastly, there is only one value of a that can make the equation true, and this value is sqrt(c2 - b2). For large values of b, it is much faster to compute this expression and to check whether it makes the equation true than to test all values between 0 and b. If you use double-precision computation for sqrt(c2 - b2), then floating-point approximations will not be an issue until N is about 226.
You can reduce one variable by the following calculations. If we assume that
a = m^2 - n^2, b = 2mn, c = m^2 + n^2
Lets check if it satisfies a^2 + b^2 = c^2:
a^2+b^2 = (m^2 - n^2)^2 + (2mn)^2 = (m^2 + n^2)^2 = c^2.
Now, we can iterate through all possible m and n and generate corresponding a, b, c.
It's the fastest method I ever used. However, I don't know if there exist any O(1) or O(log(n)) mathematical solutions.

Curve Fit 5 points

I am trying to curve fit 5 points in C. I have used this code from a previous post (Can sombody simplify this equation for me?) to do 4 points, but now I need to add another point.
// Input data: arrays x[] and y[]
// x[1],x[2],x[3],x[4] - X values
// y[1],y[2],y[3],y[4] - Y values
// Calculations
A = 0
B = 0
C = 0
D = 0
S1 = x[1] + x[2] + x[3] + x[4]
S2 = x[1]*x[2] + x[1]*x[3] + x[1]*x[4] + x[2]*x[3] + x[2]*x[4] + x[3]*x[4]
S3 = x[1]*x[2]*x[3] + x[1]*x[2]*x[4] + x[1]*x[3]*x[4] + x[2]*x[3]*x[4]
for i = 1 to 4 loop
C0 = y[i]/(((4*x[i]-3*S1)*x[i]+2*S2)*x[i]-S3)
C1 = C0*(S1 - x[i])
C2 = S2*C0 - C1*x[i]
C3 = S3*C0 - C2*x[i]
A = A + C0
B = B - C1
C = C + C2
D = D - C3
end-loop
// Result: A, B, C, D
I have been trying to covert this to a 5 point curve fit, but am having trouble figuring out what goes inside the loop:
// Input data: arrays x[] and y[]
// x[1],x[2],x[3],x[4],x[5] - X values
// y[1],y[2],y[3],y[4],y[5] - Y values
// Calculations
A = 0
B = 0
C = 0
D = 0
E = 0
S1 = x[1] + x[2] + x[3] + x[4]
S2 = x[1]*x[2] + x[1]*x[3] + x[1]*x[4] + x[2]*x[3] + x[2]*x[4] + x[3]*x[4]
S3 = x[1]*x[2]*x[3] + x[1]*x[2]*x[4] + x[1]*x[3]*x[4] + x[2]*x[3]*x[4]
S4 = x[1]*x[2]*x[3]*x[4] + x[1]*x[2]*x[3]*[5] + x[1]*x[2]*x[4]*[5] + x[1]*x[3]*x[4]*[5] + x[2]*x[3]*x[4]*[5]
for i = 1 to 4 loop
C0 = ??
C1 = ??
C2 = ??
C3 = ??
C4 = ??
A = A + C0
B = B - C1
C = C + C2
D = D - C3
E = E + C4
end-loop
// Result: A, B, C, D, E
any help in filling out the C0...C4 would be appreciated. I know this has to do with the matrices but I have not been able to figure it out. examples with pseudo code or real code would be most helpful.
thanks
I refuse to miss this opportunity to generalize. :)
Instead, we're going to learn a little bit about Lagrange polynomials and the Newton Divided Difference Method of their computation.
Lagrange Polynomials
Given n+1 data points, the interpolating polynomial is
where l_j(i) is
.
What this means is that we can find the polynomial approximating the n+1 points, regardless of spacing, etc, by just summing these polynomials. However, this is a bit of a pain and I wouldn't want to do it in C. Let's take a look at Newton Polynomials.
Newton Polynomials
Same start, given n+1 data points, the approximating polynomial is going to be
where each n(x) is
with a coefficient of
, being the divided difference.
The final form end's up looking like
.
As you can see, the formula is pretty easy given the divided difference values. You just do each new divided difference and multiply by each point so far. It should be noted that you'll end up with a polynomial of degree n from n+1 points.
Divided Difference
All that's left is to define the divided difference which is really best explained by these two pictures:
and
.
With this information, a C implementation should be reasonable to do. I hope this helps and I hope you learned something! :)
If the x values are equally spaced with x2-x1=h, x3-x2=h, x4-x3=h and x5-x4=h then
C0 = y1;
C1 = -(25*y1-48*y2+36*y3-16*y4+3*y5)/(12*h);
C2 = (35*y1-104*y2+114*y3-56*y4+11*y5)/(24*h*h);
C3 = -(5*y1-18*y2+24*y3-14*y4+3*y5)/(12*h*h*h);
C4 = (y1-4*y2+6*y3-4*y4+y5)/(24*h*h*h*h);
y(x) = C0+C1*(x-x1)+C2*(x-x1)^2+C3*(x-x1)^3+C4*(x-x1)^4
// where `^` denotes exponentiation (and not XOR).

Average of 3 numbers using integers

I would like to compute the average of three numbers, like:
d = int(round((a + b + c) / 3.0))
Where a, b, c, d are integers.
Is it possible to get the same result using just integers?
I'm interested in this because of performance reasons, I assume doing the math using integers should be faster than using floats.
The example above converts the integers to floats, calculates the result, rounds it and converts back to integer. Is it possible to avoid the int <-> float conversions?
Given the requirements for 1, 1, 2 -> 1; 1, 2, 2 -> 2 then this can be done using integer division.
Using // for the integer division and n for number of elements.
average = ( a+ b + c + .... + n//2 ) // n
ie sum up all the values and then add a number to deal with rounding.
As noted in #Henrik's answer this assumes that all numbers are positive.
(a + b + c + 1) / 3
Explanation: if (a + b + c) % 3 == 1, it's rounded down; if (a + b + c) % 3 == 2, it's rounded up.
At least this should work for a + b + c >= 0. You may need to treat negative values separately.
A variant of Mahmoud's answer using only one division:
d = (((a+b+c) * 10) + 15) / 30
It should be as simple as that:
d = (((a+b+c) * 10) / 3 + 5) / 10;

Calculation of cubic Bézier with known halfway point

I know:
The control points a and d (start and end point of a 2D cubic bezier curve)
The slopes a->b, c->d, and b->c (b,c the other control points)
Where the halfway point of the Bézier curve is.
Now, given this information, what is the formula for the positions of control points b and c ?
I know this question is old, but there is no correct or complete answer provided, so I thought I'd chime in with a solution. Note that David's calculations contain several errors and his solution is incomplete even if these errors are corrected.
First, define vectors T0, T1 and T2 using the three slopes:
T0 = ( b - a ) / u0
T1 = ( c - b ) / u1
T2 = ( d - c ) / u2
If we knew both the direction and distance between each pair of control points then we would not need the scale factors u0, u1 and u2. Since we only know slope then u0, u1 and u2 are unknown scalar quantities. Also, we assume that u0, u1 and u2 are nonzero since slope is defined.
We can rewrite these equations in several different ways to obtain expressions for each control point in terms of the other control points. For example:
b = a + T0*u0
c = b + T1*u1
d = c + T2*u2
The question also states that we have the "halfway point" of the cubic Bezier curve. I take this to mean we have the point at the midpoint of the curve's parameter range. I will call this point p:
p = ( a + 3*b + 3*c + d ) / 8
Rewriting with unknowns on the left hand side yields:
b + c = ( 8*p - a - d ) / 3
We can now substitute for b and c in various ways using the earlier expressions. It turns out that ambiguities arise when we have parallel vectors T0, T1 or T2. There are four cases to consider.
Case 1: T0 is not parallel to T1
Substitute b = a + T0*u0 and c = a + T0*u0 + T1*u1 and solve for u0 and u1:
2*T0*u0 + T1*u1 = ( 8*p - 7*a - d ) / 3
This is two equations and two unknowns since T0 and T1 are vectors. Substitute u0 and u1 back into b = a + T0*u0 and c = a + T0*u0 + T1*u1 to obtain the missing control points b and c.
Case 2: T1 is not parallel to T2
Substitute c = d - T2*u2 and b = d - T2*u2 - T1*u1 and solve for u1 and u2:
T1*u1 + 2*T2*u2 = ( a + 7*d - 8*p ) / 3
Case 3: T0 is not parallel to T2
Substitute b = a + T0*u0 and c = d - T2*u2 and solve for u0 and u2:
T0*u0 - T2*u2 = ( 8*p - 4*a - 4*d ) / 3
Case 4: T0, T1 and T2 are all parallel
In this case a, b, c and d are all collinear and T0, T1 and T2 are all equivalent to within a scale factor. There is not enough information to obtain a unique solution. One simple solution would be to simply pick b by setting u0 = 1:
b = a + T0
(a + T0) + c = ( 8*p - a - d ) / 3
c = ( 8*p - 4*a - d - 3*T0 ) / 3
An infinite number of solutions exist. In essence, picking b defines c or picking c will define b.
Extending to 3D
The question specifically asked about planar Bezier curves, but I think it's interesting to note that the point p is not necessary when extending this problem to a non-planar 3D cubic Bezier curve. In this case, we can simply solve this equation for u0, u1 and u2:
T0*u0 + T1*u1 + T2*u2 = d - a
This is three equations (the vectors are 3D) and three unknowns (u0, u1 and u2). Substitution into b = a + T0*u0 and c = b + T1*u1 or c = d - T2*u2 yields b and c.
Let's say your slopes are normalized, then for some u,v you have
u * slope(a->b)+a = b, v * slope(c->d)+d = c
you know the values of a,d, and q:=(a+b+c+d)/8 (the halfway point of the curve)
so c = 8(q-a-d-b)
plugging the above equations in the last one you get
v * slope(c->d)+d = 8(q-a-d-a-u * slope(a->b))
which is 2 equations (a 2d vector equation) in two variables (u,v)
You don't need the third slope.

Resources