How map/tween a number based on a dynamic curve - parametric-equations

I am really lacking terminology here, so any help with that appreciate. Even it doesn't answer the question it can hopefully get me closer to an answer.
How can I get y from a function of p where the curviness is also a variable (possible between 0 and 1? Or whatever is best?).
I am presuming p is always between 1 and 0, as is the output y.
The graphic is just an illustration, I don't need that exact curve but something close to this idea.
Pseudo code is good enough as an answer or something c-style (c, javascript, etc).
To give a little context, I have a mapping function where one parameter can be the – what I have called – easing function. There are based on the penner equations. So, for example if I wanted to do a easeIn I would provide:
function (p) { return p * p; };
But I would love to be able to do what is in the images: varying the ease dynamically. With a function like:
function (p, curviness) { return /* something */; }

You might try messing around with a Superellipse, it seems to have the shape malleability you're looking for. (Special case: Squircle)
Update
Ok, so the equation for the superellipse is as follows:
abs(x/a)^n + abs(y/b)^n = 1
You're going to be working in the range from [0,1] in both so we can discard the absolute values.
The a and b are for the major and minor ellipse axes; we're going to set those to 1 (so that the superellipse only stretches to +/-1 in either direction) and only look at the first quadrant ([0, 1], again).
This leaves us with:
x^n + y^n = 1
You want your end function to look something like:
y = f(p, n)
so we need to get things into that form (solve for y).
Your initial thought on what to do next was correct (but the variables were switched):
y^n = 1 - p^n
substituting your variable p for x.
Now, initially I'd thought of trying to use a log to isolate y, but that would mean we'd have to take log_y on both sides which would not isolate it. Instead, we can take the nth root to cancel the n, thus isolating y:
y = nthRoot(n, 1 - p^n)
If this is confusing, then this might help: square rooting is just raising to a power of 1/2, so if you took a square root of x you'd have:
sqrt(x) == x^(1/2)
and what we did was take the nth root, meaning that we raised things to the 1/n power, which cancels the nth power the y had since you'd be multiplying them:
(y^n)^(1/n) == y^(n * 1/n) == y^1 == y
Thus we can write things as
y = (1 - p^n)^(1/n)
to make things look better.
So, now we have an equation in the form
y = f(p, n)
but we're not done yet: this equation was working with values in the first quadrant of the superellipse; this quadrant's graph looks different from what you wanted -- you wanted what appeared in the second quadrant, only shifted over.
We can rectify this by inverting the graph in the first quadrant. We'll do this by subtracting it from 1. Thus, the final equation will be:
y = 1 - (1 - p^n)^(1/n)
which works just fine by my TI-83's reckoning.
Note: In the Wikipedia article, they mention that when n is between 0 and 1 then the curve will be bowed down/in, when n is equal to 1 you get a straight line, and when n is greater than 1 then it will be bowed out. However, since we're subtracting things from 1, this behavior is reversed! (So 0 thru 1 means it's bowed out, and greater than 1 means it's bowed in).
And there you have it -- I hope that's what you were looking for :)

Your curviness property is the exponent.
function(p, exp) { return Math.pow(p, exp); }
exp = 1 gives you the straight line
exp > 1 gives you the exponential lines (bottom two)
0 < exp < 1 gives you the logarithmic lines (top two)
To get "matching" curviness above and below, an exp = 2 would match an exp = 1/2 across the linear dividing line, so you could define a "curviness" function that makes it more intuitive for you.
function curvyInterpolator(p, curviness) {
curviness = curviness > 0 ? curviness : 1/(-curviness);
return Math.pow(p, curviness);
}

Related

Check whether A and B exists for the given values AorB and APlusB

Problem Statement:
You are given two non-negative integers: the longs pairOr and pairSum.
Determine whether it is possible that for two non-negative integers A and B we have both:
A or B = pairOr
A + B = pairSum
Above, "or" denotes the bitwise-or operator.
Return True if we can find such A and B, and False if not.
My Algorithm goes like this:
I've taken the equation: A | B = X and A + B =Y,
Now after substituting A's value from 2nd Equation, (Y-B) | B= X.
I'm going to traverse from 0 till Y (in place of B) to check if the above equation is true.
Code Snippet:
boolean isPossible(long orAandB,long plusAandB) {
for(long i=0;i<=plusAandB;i++) {
if(((plusAandB-i)|i)==orAandB ){
return true;
}
}
return false;
It will give TLE if the value of plusAndB is of number 10^18. Could you please help me optimize?
You don't need the full iteration, giving O(N). There's a way to do it in O(logN).
But completely solving the problem for you takes away most of the fun... ;-), so here's the main clue:
Your equation (Y-B) | B= X is one great observation, and the second is to have a look at this equation bit by bit, starting from the right (so you don't have to worry about borrow-bits in the first place). Which last-bit combinations of Y, X, and B can make your equation true? And if you found a B bit, how do you continue recursively with the higher bits (don't forget that subtraction may need a borrow)? I hope you remember the rules for subtracting binary numbers.
And keeping in mind that the problem only asks for true or false, not for any specific A or B value, can save you exponential complexity.

Implementing the square root method through successive approximation

Determining the square root through successive approximation is implemented using the following algorithm:
Begin by guessing that the square root is x / 2. Call that guess g.
The actual square root must lie between g and x/g. At each step in the successive approximation, generate a new guess by averaging g and x/g.
Repeat step 2 until the values of g and x/g are as close together as the precision of the hardware allows. In Java, the best way to check for this condition is to test whether the average is equal to either of the values used to generate it.
What really confuses me is the last statement of step 3. I interpreted it as follows:
private double sqrt(double x) {
double g = x / 2;
while(true) {
double average = (g + x/g) / 2;
if(average == g || average == x/g) break;
g = average;
}
return g;
}
This seems to just cause an infinite loop. I am following the algorithm exactly, if the average equals either g or x/g (the two values used to generate it) then we have our answer ?
Why would anyone ever use that approach, when they could simply use the formulas for (2n^2) = 4n^2 and (n + 1)^2 = n^2 + 2n + 1, to populate each bit in the mantissa, and divide the exponent by two, multiplying the mantissa by two iff the the mod of the exponent with two equals 1?
To check if g and x/g are as close as the HW allow, look at the relative difference and compare
it with the epsilon for your floating point format. If it is within a small integer multiple of epsilon, you are OK.
Relative difference of x and y, see https://en.wikipedia.org/wiki/Relative_change_and_difference
The epsilon for 32-bit IEEE floats is about 1.0e-7, as in one of the other answers here, but that answer used the absolute rather than the relative difference.
In practice, that means something like:
Math.abs(g-x/g)/Math.max(Math.abs(g),Math.abs(x/g)) < 3.0e-7
Never compare floating point values for equality. The result is not reliable.
Use a epsilon like so:
if(Math.abs(average-g) < 1e-7 || Math.abs(average-x/g) < 1e-7)
You can change the epsilon value to be whatever you need. Probably best is something related to the original x.

Chris Pine Ruby ch 10, recursion

I have been trying to learn ruby using the book 'learn to program' by Chris Pine. I was actually getting excited when going through the book until I got to chapter 10 and the examples used. Now this chapter alone and its examples have completely deflated all of my excitement to continue with this book. In this example I have completely no idea how its trying to count the tiles, or why he uses world [y],[x] when the method was defined with the attribute of continent_size world, x,y? Im not sure how the recursion in this example works. Can someone shed some more light onto this example as to what the author was actually trying to do?
M = 'land'
o = 'water'
world = [
[o,o,o,o,o,M,o,o,o,o,o],
[o,o,o,o,M,M,o,o,o,o,o],
[o,o,o,o,o,M,o,o,M,M,o],
[o,o,o,M,o,M,o,o,o,M,o],
[o,o,o,o,o,M,M,o,o,o,o],
[o,o,o,o,M,M,M,M,o,o,o],
[M,M,M,M,M,M,M,M,M,M,M],
[o,o,o,M,M,o,M,M,M,o,o],
[o,o,o,o,o,o,M,M,o,o,o],
[o,M,o,o,o,M,M,o,o,o,o],
[o,o,o,o,o,M,o,o,o,o,o]]
def continent_size world, x ,y
if x < 0 or x > 10 or y < 0 or y > 10
return 0
end
if world[y][x] != 'land'
return 0
end
size = 1
world [y][x] = 'counted land'
size = size + continent_size(world, x-1, y-1)
size = size + continent_size(world, x , y-1)
size = size + continent_size(world, x+1, y-1)
size = size + continent_size(world, x-1, y )
size = size + continent_size(world, x+1, y )
size = size + continent_size(world, x-1, y+1)
size = size + continent_size(world, x , y+1)
size = size + continent_size(world, x+1, y+1)
size
end
puts continent_size(world, 5, 5)
This is called a flood fill. What it's doing is counting the size of all the pieces of 'land' that are connected to the initial starting point. Note that it doesn't count all of the 'land' symbols, just the ones on that it can't get to because of water.
Flood fill is a form of something called depth first search which is a way to traverse a graph (here, a discrete 'map'). It can be summarized like so:
Visit the current position/graph node, count it and mark it as visited
Check all connected nodes (here, anything up, down, left or right), if they are not visited and they are land, recursively visit them
He might be doing y, x for the following reason: the logical format of a 2D array is organized first by row, then by column. The row could be thought of as the y axis and the column as the x.
For what it's worth I when I worked through this problem in the book I also noticed the transposition of x & y when world is called. I looked on the Pragmatic Programmer's website to see if this was listed in the errata, but it is not.
I thought it was typo and flipped them to x, y. The code works either way.
It doesn't really matter, since the starting point of 5,5 is arbitrary and the code will check all eight tiles around x,y (or y,x) regardless until it hits the "edge" of the array/world.
Taking a few steps back from the other answers, the recursion here is in that continent_size is called eight times from within continent_size.
So the method is being called eight times inside itself.
But ... each of those eight inner methods call continent_size a further eight times.
And so on, and so on.
It's bonkers to get your head around it, but when you do, it feels like you can see The Matrix. Albeit very briefly.
I stumbled across this question looking for some help with the extension bit of the task (how to avoid the error if one of your 'explorers' falls off the edge of the world).
I ended up solving this with a rescue:
# If it's off the edge of the world, it's as good as water
square = world[y][x] rescue 'o'
if square != 'Land'
return 0
end
I don't know if this is the best way to do it, but it seems quite elegant to me.
I feel pretty dirty about the way I solved it, and am here looking for a better answer. I created a new variable, E = 'edge', and changed any character that touched the edge of the map to E. Then I added this code to the top of the continent_size method:
if world[y][x] == 'edge'
return 1
end
It works. :/
It looks like the rescue approach still crashes when the top edge of the world is all 'o's. A simple approach to solving this is to write a conditional that checks if either coordinate (x,y) is outside of the boundary (i.e. outside of 0 or world.length-1) and return 0 if that condition is met.
I also noticed the transposition of x and y in Pine's code.
I think the reasoning might be that he arranged the "world" array so that there is one sub-array on each line. The first number in square brackets following "world" (world[0]) refers to the index of the element (sub-array) within world. Since these are stacked vertically it is your y-axis. The second bracketed number (world[0][5]) refers to the element within the sub-array. These run horizontally so the second number refers to your x-axis. Writing the method to take parameter x then parameter y allows you to enter the staring location in the conventional (x,y) format while within the method the variables are transposed to accomplish the task. I think. I'm completely new to this though.
Also, if anyone has a clean solution to extended version of this exercise where where the continent "borders the edge of the world" I would love to see it
It also took me some time to get the head around this example. I tried to solve the task like this, at first:
if ( world[y] > world[y].length || world[x] > world[x].length ) || ( world[y] < world[y].length || world[x] < world[x].length )
return 0
end
But I kept getting errors of the "undefined method ">" for an array"
I then realised that the solution could be in conditioning "x" and "y", if they are more than an array (10) or lower than (0):
if x > 10 || x < 0 || y > 10 || y < 0
return 0
end
The problem here is that it works on this particular size of arrays...if the world is bigger than 10 - the program would count every "land" it encounters as 0.
So I guess it's half-solution only...

How to implement Random(a,b) with only Random(0,1)? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
how to get uniformed random between a, b by a known uniformed random function RANDOM(0,1)
In the book of Introduction to algorithms, there is an excise:
Describe an implementation of the procedure Random(a, b) that only makes calls to Random(0,1). What is the expected running time of your procedure, as a function of a and b? The probability of the result of Random(a,b) should be pure uniformly distributed, as Random(0,1)
For the Random function, the results are integers between a and b, inclusively. For e.g., Random(0,1) generates either 0 or 1; Random(a, b) generates a, a+1, a+2, ..., b
My solution is like this:
for i = 1 to b-a
r = a + Random(0,1)
return r
the running time is T=b-a
Is this correct? Are the results of my solutions uniformly distributed?
Thanks
What if my new solution is like this:
r = a
for i = 1 to b - a //including b-a
r += Random(0,1)
return r
If it is not correct, why r += Random(0,1) makes r not uniformly distributed?
Others have explained why your solution doesn't work. Here's the correct solution:
1) Find the smallest number, p, such that 2^p > b-a.
2) Perform the following algorithm:
r=0
for i = 1 to p
r = 2*r + Random(0,1)
3) If r is greater than b-a, go to step 2.
4) Your result is r+a
So let's try Random(1,3).
So b-a is 2.
2^1 = 2, so p will have to be 2 so that 2^p is greater than 2.
So we'll loop two times. Let's try all possible outputs:
00 -> r=0, 0 is not > 2, so we output 0+1 or 1.
01 -> r=1, 1 is not > 2, so we output 1+1 or 2.
10 -> r=2, 2 is not > 2, so we output 2+1 or 3.
11 -> r=3, 3 is > 2, so we repeat.
So 1/4 of the time, we output 1. 1/4 of the time we output 2. 1/4 of the time we output 3. And 1/4 of the time we have to repeat the algorithm a second time. Looks good.
Note that if you have to do this a lot, two optimizations are handy:
1) If you use the same range a lot, have a class that computes p once so you don't have to compute it each time.
2) Many CPUs have fast ways to perform step 1 that aren't exposed in high-level languages. For example, x86 CPUs have the BSR instruction.
No, it's not correct, that method will concentrate around (a+b)/2. It's a binomial distribution.
Are you sure that Random(0,1) produces integers? it would make more sense if it produced floating point values between 0 and 1. Then the solution would be an affine transformation, running time independent of a and b.
An idea I just had, in case it's about integer values: use bisection. At each step, you have a range low-high. If Random(0,1) returns 0, the next range is low-(low+high)/2, else (low+high)/2-high.
Details and complexity left to you, since it's homework.
That should create (approximately) a uniform distribution.
Edit: approximately is the important word there. Uniform if b-a+1 is a power of 2, not too far off if it's close, but not good enough generally. Ah, well it was a spontaneous idea, can't get them all right.
No, your solution isn't correct. This sum'll have binomial distribution.
However, you can generate a pure random sequence of 0, 1 and treat it as a binary number.
repeat
result = a
steps = ceiling(log(b - a))
for i = 0 to steps
result += (2 ^ i) * Random(0, 1)
until result <= b
KennyTM: my bad.
I read the other answers. For fun, here is another way to find the random number:
Allocate an array with b-a elements.
Set all the values to 1.
Iterate through the array. For each nonzero element, flip the coin, as it were. If it is came up 0, set the element to 0.
Whenever, after a complete iteration, you only have 1 element remaining, you have your random number: a+i where i is the index of the nonzero element (assuming we start indexing on 0). All numbers are then equally likely. (You would have to deal with the case where it's a tie, but I leave that as an exercise for you.)
This would have O(infinity) ... :)
On average, though, half the numbers would be eliminated, so it would have an average case running time of log_2 (b-a).
First of all I assume you are actually accumulating the result, not adding 0 or 1 to a on each step.
Using some probabilites you can prove that your solution is not uniformly distibuted. The chance that the resulting value r is (a+b)/2 is greatest. For instance if a is 0 and b is 7, the chance that you get a value 4 is (combination 4 of 7) divided by 2 raised to the power 7. The reason for that is that no matter which 4 out of the 7 values are 1 the result will still be 4.
The running time you estimate is correct.
Your solution's pseudocode should look like:
r=a
for i = 0 to b-a
r+=Random(0,1)
return r
As for uniform distribution, assuming that the random implementation this random number generator is based on is perfectly uniform the odds of getting 0 or 1 are 50%. Therefore getting the number you want is the result of that choice made over and over again.
So for a=1, b=5, there are 5 choices made.
The odds of getting 1 involves 5 decisions, all 0, the odds of that are 0.5^5 = 3.125%
The odds of getting 5 involves 5 decisions, all 1, the odds of that are 0.5^5 = 3.125%
As you can see from this, the distribution is not uniform -- the odds of any number should be 20%.
In the algorithm you created, it is really not equally distributed.
The result "r" will always be either "a" or "a+1". It will never go beyond that.
It should look something like this:
r=0;
for i=0 to b-a
r = a + r + Random(0,1)
return r;
By including "r" into your computation, you are including the "randomness" of all the previous "for" loop runs.

OpenCV: parabola detection using Hough Transform

I want to detect parabola(s) of type : y^2 = 4a*x in an image[size: 512 X 512]. I prepared an accumulator array, acc[size: 512 X 512 X 512]. I prepared a MATRIX corresponding to that image. I used hough-transform. This is how I did it:
for x = 1 to 512
for y= 1 to 512
if image_matrix(x,y)> 245//almost white value, so probable to be in parabola
{
for x1= 1 to 512
for y1= 1 to 512
{
calculate 'a' from (y-y1)^2 = 4*a*(x-x1).
increment acc(i,j,k) by 1
}
}
if acc(i,j,k) has a maximum value.
{
x1=i, y1=j,a =k
}
I faced following problems:
1) acc[512][512][512] takes large memory. It needs huge computation.How can I decrease array size and thus minimize computation?
2) Not always max valued-entry of acc(i,j,k) give intended output. Sometimes second or third maximum, and even 10'th maximum value give the intended output. I need approx. value of 'a', 'x1','y1'(not exact value).
Please help me. Is there any wrong in my concept?
What i'm going to say may only partly answer your question, but it should work.
If you want to find these type of parabolas
y^2 = 4a*x
Then they are parametrized by only one parameter which is 'a'. Therefore, i don't really understand why you use a accumulator of 3 dimensions.
For sure, if you want to find a parabola with a more general equation like :
y = ax^2 + bx + c
or in the y direction by replacing x by y, you will need a 3-dimension accumulator like in your example.
I think in your case the problem could be solved easily, saying you only need one accumulator (as you have only one parameter to accumulate : a)
That's what i would suggest :
for every point (x,y) of your image (x=0 exclusive) {
calculate (a = y^2 / 4x )
add + 1 in the corresponding 'a' cell of your accumulator
(eg: a = index of a simple table)
}
for all the cells of your accumulator {
if (cell[idx] > a certain threshold) there is a certain parabola with a = idx
}
I hope it can help you,
This is as well an interesting thing to look at :
Julien,

Resources