My professor gave us an assignment to test the difference in runtimes and search sizes using linear & binary algorithms, and the data is to be graphed.
I have the search methods put the runtime & array sizes as Points in an ArrayList, which is then sent to the GraphResults class for plotting. I need to convert those data points into xy coordinates before. The search size is the x-axis and the runtime is the y axis
As the search sizes are fixed as a multiple of 128 and there are only 8 sizes, I used switch for calculating the x value, but am looking for a more efficient way to convert the runtimes into coordinates.
Right now, I'm using nested conditionals with 5 like this:
if (y<=1000) {
if (y<= 500) {
if (y<= 250) {
newy= yaxis-32; }//equals to 250ms category
else {
newy= yaxis-(32*2); }//500ms category
}
else if (y<=750) {
newy= yaxis-(32*3);} //750ms category
else {
newy= yaxis-(32*4);} //1000ms category
} //end of the 1000ms tests
Right now, the numbers that are over 5000ms require 7 tests. Is there a more efficient way to assign a number based on a number size?
As you are trying to determine the range of your measurement, you can divide the amount by the range size, followed by calculating the number you want to show in the graph.
Btw, in your code, you made a logic error, if the value is y <= 1000 the first condition evaluates to true, and the second for y <= 750 will never be evaluated.
Also it seems that the higher the value range, the lower your graph point. Is that as intended? (1000 -> ymax - 128 while 1 -> ymax - 32)
As an aside, if you want to compare values to uneven ranges, you can also do something like an array lookup (pseudo code):
int[] ranges = new int { 50, 500, 5000, 50000 };
for (int n = 0; n < ranges.length && value > ranges[n]; n++) {
}
int range = n;
int newy = yaxis - range * 32;
Note that the out-of-range index acts as the range found for a value that is bigger than the biggest value in your array.
How about newy = yaxis - 32 * ((y/250)% 8);?
I would reformat your code to something more like this:
newy = yaxis - 32 * ((y-1)/250 + 1);
This way, you're calculating the multiplier rather than choosing it manually.
Related
Another description of the problem: Compute a matrix which satisfies certain constraints
Given a function whose only argument is a 4x4 matrix (int[4][4] matrix), determine the maximal possible output (return value) of that function.
The 4x4 matrix must satisfy the following constraints:
All entries are integers between -10 and 10 (inclusively).
It must be symmetrix, entry(x,y) = entry(y,x).
Diagonal entries must be positive, entry(x,x) > 0.
The sum of all 16 entries must be 0.
The function must only sum up values of the matrix, nothing fancy.
My question:
Given such a function which sums up certain values of a matrix (matrix satisfies above constraints), how do I find the maximal possible output/return value of that function?
For example:
/* The function sums up certain values of the matrix,
a value can be summed up multiple or 0 times. */
// for this example I arbitrarily chose values at (0,0), (1,2), (0,3), (1,1).
int exampleFunction(int[][] matrix) {
int a = matrix[0][0];
int b = matrix[1][2];
int c = matrix[0][3];
int d = matrix[1][1];
return a+b+c+d;
}
/* The result (max output of the above function) is 40,
it can be achieved by the following matrix: */
0. 1. 2. 3.
0. 10 -10 -10 10
1. -10 10 10 -10
2. -10 10 1 -1
3. 10 -10 -1 1
// Another example:
// for this example I arbitrarily chose values at (0,3), (0,1), (0,1), (0,4), ...
int exampleFunction2(int[][] matrix) {
int a = matrix[0][3] + matrix[0][1] + matrix[0][1];
int b = matrix[0][3] + matrix[0][3] + matrix[0][2];
int c = matrix[1][2] + matrix[2][1] + matrix[3][1];
int d = matrix[1][3] + matrix[2][3] + matrix[3][2];
return a+b+c+d;
}
/* The result (max output of the above function) is -4, it can be achieved by
the following matrix: */
0. 1. 2. 3.
0. 1 10 10 -10
1. 10 1 -1 -10
2. 10 -1 1 -1
3. -10 -10 -1 1
I don't know where to start. Currently I'm trying to estimate the number of 4x4 matrices which satisfy the constraints, if the number is small enough the problem could be solved by brute force.
Is there a more general approach?
Can the solution to this problem be generalized such that it can be easily adapted to arbitrary functions on the given matrix and arbitrary constraints for the matrix?
You can try to solve this using linear programming techniques.
The idea is to express the problem as some inequalities, some equalities, and a linear objective function and then call a library to optimize the result.
Python code:
import scipy.optimize as opt
c = [0]*16
def use(y,x):
c[y*4+x] -= 1
if 0:
use(0,0)
use(1,2)
use(0,3)
use(1,1)
else:
use(0,3)
use(0,1)
use(0,1)
use(0,3)
use(0,3)
use(0,2)
use(1,2)
use(2,1)
use(3,1)
use(1,3)
use(2,3)
use(3,2)
bounds=[ [-10,10] for i in range(4*4) ]
for i in range(4):
bounds[i*4+i] = [1,10]
A_eq = [[1] * 16]
b_eq = [0]
for x in range(4):
for y in range(x+1,4):
D = [0]*16
D[x*4+y] = 1
D[y*4+x] = -1
A_eq.append(D)
b_eq.append(0)
r = opt.linprog(c,A_eq=A_eq,b_eq=b_eq,bounds=bounds)
for y in range(4):
print r.x[4*y:4*y+4]
print -r.fun
This prints:
[ 1. 10. -10. 10.]
[ 10. 1. 8. -10.]
[-10. 8. 1. -10.]
[ 10. -10. -10. 1.]
16.0
saying that the best value for your second case is 16, with the given matrix.
Strictly speaking you are wanting integer solutions. Linear programming solves this type of problem when the inputs can be any real values, while integer programming solves this type when the inputs must be integers.
In your case you may well find that the linear programming method already provides integer solutions (it does for the two given examples). When this happens, it is certain that this is the optimal answer.
However, if the variables are not integral you may need to find an integer programming library instead.
Sort the elements in the matrix in descending order and store in an array.Iterate through the elements in the array one by one
and add it to a variable.Stop iterating at the point when adding an element to variable decrease its value.The value stored in the variable gives maximum value.
maxfunction(matrix[][])
{
array(n)=sortDescending(matrix[][]);
max=n[0];
i=1;
for i to n do
temp=max;
max=max+n[i];
if(max<temp)
break;
return max;
}
You need to first consider what matrices will satisfy the rules. The 4 numbers on the diagonal must be positive, with the minimal sum of the diagonal being 4 (four 1 values), and the maximum being 40 (four 10 values).
The total sum of all 16 items is 0 - or to put it another way, sum(diagnoal)+sum(rest-of-matrix)=0.
Since you know that sum(diagonal) is positive, that means that sum(rest-of-matrix) must be negative and equal - basically sum(diagonal)*(-1).
We also know that the rest of the matrix is symmetrical - so you're guaranteed the sum(rest-of-matrix) is an even number. That means that the diagonal must also be an even number, and the sum of the top half of the matrix is exactly half the diagonal*(-1).
For any given function, you take a handful of cells and sum them. Now you can consider the functions as fitting into categories. For functions that take all 4 cells from the diagonal only, the maximum will be 40. If the function takes all 12 cells which are not the diagonal, the maximum is -4 (negative minimal diagonal).
Other categories of functions that have an easy answer:
1) one from the diagonal and an entire half of the matrix above/below the diagonal - the max is 3. The diagonal cell will be 10, the rest will be 1, 1, 2 (minimal to get to an even number) and the half-matrix will sum at -7.
2) two cells of the diagonal and half a matrix - the max is 9. the two diagonal cells are maximised to two tens, the remaining cells are 1,1 - and so the half matrix sums at -11.
3) three cells from the diagonal and half a matrix - the max is 14.
4) the entire diagonal and half the matrix - the max is 20.
You can continue with the categories of selecting functions (using some from the diagonal and some from the rest), and easily calculating the maximum for each category of selecting function. I believe they can all be mapped.
Then the only step is to put your new selecting function in the correct category and you know the maximum.
Given a distance d (going from 0 to d) and 2 points s and e in between which no points can be placed (placing points on s and e is fine, it's not allowed to place points between them).
Place n points such that the distance between each point is as large as possible (distribute them as evenly as possible).
Output the minimal distance between 2 points.
Graphic representation, place n points on the black line (it's a 1-dimensional line) so that the smallest distance between each 2 points is as large as possible (an absolute error of up to 10^(-4) is allowed).
Examples:
d=7, n=2, s=6, e=7, Output is: 7.0000000000
d=5, n=3, s=5, e=5, Output is: 2.5000000006
d=3, n=3, s=0, e=1, Output is: 1.5000000007
d=9, n=10, s=5, e=6, Output is: 1.0000000001
d=6, n=2, s=1, e=6, Output is: 6.0000000000
d=5, n=3, s=4, e=5, Output is: 2.5000000006
My approach:
I tried looking at the intervals separately, distributing points (ideal distribution, lengthOfInterval/n) on the first and second interval (0 to s and e to d) and inspecting all distributions whose number of points sum up to n, I would store a (distribution, largest minimal distance) pair and pick the pair with the largest minimal distance. I don't know how to work with the 10^(-4) tolerance (how does this part even look in code?) and am not sure if my approach is correct. Every suggestion is welcome.
I'm stuck on this question :/
You can use binary search over the possible sizes of gaps between points (from 0 to d) to converge to the largest minimum gap size.
To determine the viability of any given gap size, you basically try to place points from the left and from the right and see whether the gap in the middle is big enough:
Determine how many points can be placed left of s (which is s/gapSize + 1).
Determine how many points will then be required to be placed to the right of e
(which is n - points on left).
Determine how far inwards each side will go.
Check whether the points on the right fits in the gap [e, d] and whether there's at least gap size difference between each side.
Code for this: (note that I worked with number of gaps instead of points, which is just 1 less than the number of points, since it leads to simpler code)
double high = d, low = 0, epsilon = 0.000001;
while (low + epsilon < high)
{
double mid = (low + high)/2;
int gapsOnLeft = (int)(s/mid); // gaps = points - 1
if (gapsOnLeft + 1 > n)
gapsOnLeft = n - 1;
int gapsOnRight = n - gapsOnLeft - 2; // will be -1 when there's no point on the right
double leftOffset = mid*gapsOnLeft;
// can be > d with no point on the right, which makes the below check work correctly
double rightOffset = d - mid*gapsOnRight;
if (leftOffset + mid <= rightOffset && rightOffset >= e)
low = mid;
else
high = mid;
}
System.out.println(low);
Live demo.
The time complexity is O(log d).
The problem with your approach is that it's hard to figure out how big the gaps between points are supposed to be, so you won't know how many points are supposed to go on either side of (s, e) as to end up with an optimal solution and to correctly deal with both cases when s and e are really close together and when they're far apart.
Binary search
Its very easy to find the number of points you can place if the minimum separation distance b/w any pair l is given.
If l=d, then at the most only 2 points can be placed.
..
...
....
so just do a binary search on l.
A crude implementation goes like this.
low,high=0.00001,d
while(high-low>eps):
m = (low+high)/2
if((no. of points placed s.t any pair is at most m units away) >=n):
low=mid
else:
high=mid
TL;DR: Your approach does not always work (and you're not doing it as fast as you could) see the 3rd bullet point for one that works (and uses the given 10^(-4)).
If [s, e] is small and well-placed, then the optimum is just distributing evenly on the whole segment, best value is now d/(n-1). But you'll have to check that none of your elements is between s and e.
Your approach works if s and e are "far enough".
You can do it faster than what you seem to suggest though, by lookign for the best splitting between the two segments in time O(1): if you put n1 (1<=n1<=n-1) elements on the left, you want to maximize min(s/(n1-1), (d-e)/(n-n1-1)) (one of these quantities being possibly +infinity, but then the other is not). The maximum of that function is obtained for s/(x-1) = (d-e)/(n-x-1), just compute the corresponding value for x, and either its floor or ceiling is the best value for n1. The distance obtained is best = min(s/(n1-1), (d-e)/(n-n1-1)) Then you put n1 points on the left, starting at 0, separated by distance best, and n-n1 on the right, starting at d, going left, separated by best.
If the distance between the last point on the left and the first on the right is smaller than best, then you have a problem, this approach does not work.
The complicated case is when the two previous approaches failed: the hole is small and not well placed. Then there are probably many ways to solve the problem. One is to use binary search to find the optimal space between two consecutive points. Given a candidate space sp, try distributing points on the line starting at 0, spaced by sp, as many as you can while remaining below s. Do the same on the right while staying above e and above (last on the left + sp). If you have successfully placed at least n points in total, then sp is too small. Otherwise, it is too big.
Thus, you can use binary search to find the optimal spas follows: start at sp possibly in [max(s, d-e)/(n-1), d/(n-1)]. At each step, take the middle mid of your possible segment [x, y]. Check if the real optimum is above or below mid. According to your case, look for the optimum in [mid, y] or [x, mid]. Stop iff y-x < 10^(-4).
The two previous cases will actually also be found by this method, so you don't need to implement them, except if you want the exact optimal value when possible (i.e. in the first two cases).
It's pretty tricky, except for the simple case (no point lands in the gap):
double dMin = d / (n - 1.0);
if (Math.ceil(e / dMin - 1) * dMin <= s)
return dMin;
Let's continue with the edge cases, placing one point on one side and the rest of the points on the other one:
dMin = Math.min((d - e) / (n - 2.0), e); // one point at 0
double dm = Math.min(s / (n - 2.0), d - s); // one point at d
if (dm > dMin) // 2nd configuration was better
dMin = dm;
And finally for two or more points on both sides:
// left : right = (x - 1) : (n - x - 1)
// left * n - left * x - left = right * x - right
// x * (left + right) = left * n - left + right
// x = (left * n - left + right) / (left + right) = (left * n) / (left + right) - 1
int x = s * n / (d - e + s) - 1;
if (x < 2)
x = 2;
for (int y = x; y <= x + 2 && y < n - 1; y++) {
double dLeft = s / (y - 1.0);
double dRight = (d - e) / (n - y - 1.0);
dm = Math.min(dLeft, dRight);
if (dm > e - s) { // dm bigger than gap
if (dLeft > dRight)
dLeft = e / ((double) y);
else
dRight = (d - s) / ((double) n - y);
dm = Math.min(dLeft, dRight);
}
if (dm > dMin)
dMin = dm;
}
This would be O(1) space and time, but I'm not 100% positive if all cases are checked. Please let me know if it worked. Tested against all the test cases. The above works for n >= 2, if n equals 2 it will be caught by the first check.
I'd like to use my accelerometer in my car and with the accelerometer values, draw a trajectory in excel or any other platform with the origin in the first position value, that is the beginning of the path.
How can I achieve this? Please give me details I don't have any physics notion.
Please help, thanks in advance.
PS: I already programmed the SensorListener...
I have this for instance:
#Override
public void onSensorChanged(SensorEvent event){
if(last_values != null){
float dt = (event.timestamp - last_timestamp) * NS2S;
for(int index = 0 ; index < 3 ; ++index){
acceleration[index] = event.values[index];
velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
position[index] += velocity[index] * dt;
}
vxarr.add(velocity[0]);
vyarr.add(velocity[1]);
vzarr.add(velocity[2]);
axarr.add(acceleration[0]);
ayarr.add(acceleration[1]);
azarr.add(acceleration[2]);
}
else{
last_values = new float[3];
acceleration = new float[3];
velocity = new float[3];
position = new float[3];
velocity[0] = velocity[1] = velocity[2] = 0f;
position[0] = position[1] = position[2] = 0f;
}
xarr.add(position[0]);
yarr.add(position[1]);
zarr.add(position[2]);
tvX.setText(String.valueOf(acceleration[0]));
tvY.setText(String.valueOf(acceleration[1]));
tvZ.setText(String.valueOf(acceleration[2]));
last_timestamp = event.timestamp;
}
but when I draw a circle with my phone I got this:
Sometimes I have just only negative values and sometimes I have just positive values, I never have negative AND positive values in order to have circle.
Acceleration is the derivative of speed by time (in other words, rate of change of speed); speed is the derivative of position by time. Therefore, acceleration is the second derivative of position. Conversely, position is the second antiderivative of acceleration. You could take the accelerometer measurements and do the double intergration over time to obtain the positions for your trajectory, except for two problems:
1) It's an indefinite integral, i.e. there are infinitely many solutions (see e.g. https://en.wikipedia.org/wiki/Antiderivative). In this context, it means that your measurements tell you nothing about the initial speed. But you can get it from GPS (with limited accuracy) or from user input in some form (e.g. assume the speed is zero when the user hits some button to start calculating the trajectory).
2) Error accumulation. Suppose the accelerometer error in any given direction a = 0.01 m/s^2 (a rough guess based on my phone). Over t = 5 minutes, this gives you an error of a*t^2/2 = 450 meters.
So you can't get a very accurate trajectory, especially over a long period of time. If that doesn't matter to you, you may be able to use code from the other answer, or write your own etc. but first you need to realize the very serious limitations of this approach.
How to calculate the position of the device using the accelerometer values?
Physicists like to think of the position in space of an object at a given time as a mathematical function p(t) with values ( x(t), y(t), z(t) ). The velocity v(t) of that object turns out to be the first derivative of p(t), and the acceleration a(t) nicely fits in as the first derivative of v(t).
From now on, we will just look at one dimension, the other two can be treated in the same way.
In order to get the velocity from the acceleration, we have to "reverse" the operation using our known initial values (without them we would not obtain a unique solution).
Another problem we are facing is that we don't have the acceleration as a function. We just have sample values handed to us more or less frequently by the accelerometer sensor.
So, with a prayer to Einstein, Newton and Riemann, we take these values and think of the acceleration function as a lot of small lines glued together. If the sensor fires often, this will be a very good approximation.
Our problem now has become much simpler: the (indefinite) integral (= antiderivative) to a linear function
f(t) = m*t + b is F(t) = m/2 * t^2 + b*t + c, where c can be chosen to satisfy the initial condition (zero velocity in our case) .
Let's use the point-slope form to model our approximation (with time values t0 and t1 and corresponding acceleration values a0 and a1):
a(t) = a0 + (a1 – a0)/(t1 – t0) * (t – t0)
Then we get (first calculate v(t0) + "integral-between-t0-and-t-of-a", then use t1 in place of t)
v(t1) = v(t0) + (a1 + a0) * (t1 – t0) / 2
Using the same logic, we also get a formula for the position:
p(t1) = p(t0) + (v(t1) + v(t0)) * (t1 – t0) / 2
Translated into code, where last_values is used to store the old acceleration values:
float dt = (event.timestamp - last_timestamp) * NS2S;
for(int index = 0 ; index < 3 ; ++index){
acceleration[index] = event.values[index];
float last_velocity = velocity[index];
velocity[index] += (acceleration[index] + last_values[index])/2 * dt;
position[index] += (velocity[index] + last_velocity )/2 * dt;
last_values[index] = acceleration[index];
}
**EDIT: **
All of this is only useful for us as long as our device is aligned with the world's coordinate system. Which will almost never be the case. So before calculating our values like above, we first have to transform them to world coordinates by using something like the rotation matrix from SensorManager.getRotationMatrix().
There is a code snippet in this answer by Csaba Szugyiczki which shows how to get the rotation matrix.
But as the documentation on getRotationMatrix() states
If the device is accelerating, or placed into a strong magnetic field, the returned matrices may be inaccurate.
...so I'm a bit pessimistic about using it while driving a car.
I have a simple recursive solution as below:
public int countPaths(int x, int y) {
if(x == 0 && y == 0) {
return 0;
} else if(x == 0) {
return 1;
} else if(y == 0) {
return 1;
} else {
int count = countPaths(x-1, y);
count += countPaths(x, y-1);
return count;
}
}
This is to solve the following problem from the book: Cracking the coding interview
Imagine a robot sitting on the upper left corner of an X by Y grid. The robot can only move in two directions: right and down. How many possible paths are there for the robot to go from (0,0) to (X,Y)?
I am trying to ascertain the run time complexity and I believe it is O(x+y). I arrived at this by using a recursion tree, for example if x=2 and y=2
The max depth of this tree is (x+y) and work done at each step is a constant. So max work done is (x+y) * c and hence the run time complexity is O(x+y)
Question 1: Am I correct? I believe the upper bound I have calculated is not tight enough
Question 2: Next, if I were to improve the run time using memoization and hence not repeating computing sub-problems, how would the run time complexity as described by Big-o change?
While it's true that the depth of the tree is O(x+y), there's increasingly many nodes at each layer, and it's the number of nodes that determines complexity, not the depth of the tree.
If you write down recurrence relations for the runtime, you get:
T(0, y) = T(x, 0) = 1
T(x, y) = T(x-1, y) + T(x, y-1) + 1
If you ignore the +1 on the second equation (which can only make the run-time better), you get the same function that your code was computing in the first place, which is choose(x+y, y).
For x=y, this is the central binomial coefficient, which is approximately 4^x/sqrt(pi*x), which for even moderately large values of x is large enough to make the algorithm useless.
With memoisation, you're doing a constant amount of work for each value of x and y, so the complexity is O(xy).
If you evaluate the complexity in terms of the number of additions required to evaluate the count for a given pair (x, y), you get the recurrence
A(x,y) = A(x-1,y) + A(x,y-1) + 1,
with A(x,0) = A(0,y) = 0.
Setting A(x,y) = P(x,y) - 1 the recurrence becomes
P(x,y) - 1 = P(x-1,y) - 1 + P(x,y-1) - 1 + 1,
or
P(x,y) = P(x-1,y) + P(x,y-1),
with P(x,0) = P(0,y) = 1, which gives the classical Pascal's triangle, and
A(x,y) = (x+y)!/(x!y!) - 1.
You can also work with the number of recursive function calls,
C(x,y) = C(x-1,y) + C(x,y-1) + 2,
with C(0,y) = C(x,0) = 0.
You will solve it by setting C(x,y) = 2P(x,y) - 2, and get
C(x,y)= 2(x+y)!/(x!y!)-2.
As regards the asymptotic complexity, this makes no difference. The is no really simpler formula than O((x+y)!/x!y!).
With memoization, every evaluation (with x, y>0) costs only one addition or two calls, and assuming constant time for storage/retrieval of a value the total complexity is the much better O(xy).
Based on the valuable input from #Anonymous, we know the recurrence relation is:
T(x, y) = T(x-1, y) + T(x, y-1) + 1
Abusing (which is ok in Big-O analysis) the notation, let x = y
T(x, x) = 2 * T(x-1, x) = 2 * 2 * T(x-2, x) = ... = 2 * ... * 2 * T(0, x)
= O(2^x)
So the run time complexity is
O(2^n) ; where n = max(x, y)
With memoization, I get it, thank #Anonymous, it should be O(xy)
My particular case of summing digits deals with colors represented as integer. Java function BufferedImage.getRGB returns image in 0x00RRGGBB format. I'm making a function that gives you grayscale (color independent) sum of colors on the image. Currently, my operation looks very naive:
//Just a pseudocode
int sum = 0;
for(x->width) {
for(y->height) {
int pixel = image.getRGB(x,y);
sum+=(pixel&0x00FF0000)+(pixel&0x0000FF00)+(pixel&0x000000FF);
}
}
//The average value for any color then equals:
float avg = sum/(width*height*3);
I was wondering if I could do it even faster with some bit-shifting logic. And I am mostly asking this question to learn more about bit-shifting as I doubt any answer will speed up the program really significantly.
R, G and B do not attribute equally to the perceived intensity. A better way to sum things up than this:
sum+=(pixel&0x00FF0000)+(pixel&0x0000FF00)+(pixel&0x000000FF);
Would be, with the necessary bitshifting and weighing (assuming 00RRGGBB):
sum+= ((pixel&0x00FF0000)>>16) * .30 / 255
+ ((pixel&0x0000FF00)>> 8) * .59 / 255
+ (pixel&0x000000FF) * .11 / 255;
You might want to leave the /255 part out here and replace the floating point numbers with scaled-up integer numbers (like 30, 59 and 11), bearing in mind that you'll need a long sum to prevent overflow to a reasonable degree.