Related
This is the expression given as solution in the book I referred to but it seems to be beyond my understanding. Please anyone help to understand how are we exactly writing this angle? Why subtract pi/2? I really have no idea
xs=(int)(Math.cos(s*3.14f/30-3.14f/2)*45+xcentre);
ys=(int)(Math.sin(s*3.14f/30-3.14f/2)*45+ycentre);
xm=(int)(Math.cos(m*3.14f/30-3.14f/2)*40+xcentre);
ym=(int)(Math.sin(m*3.14f/30-3.14f/2)*40+ycentre);
xh=(int)(Math.cos((h*30+m/2)*3.14f/180-3.14f/2)*30+xcentre);
yh=(int)(Math.sin((h*30+m/2)*3.14f/180-3.14f/2)*30+ycentre);
Seems like it's giving the cartesian coordinates of the ends of the three hands of a clock centered at the origin, with up being negative y, and right being positive x. I can say this just by trying some values.
I wrapped your basic code like this:
static class ClockCoords {
int xs, ys;
int xm, ym;
int xh, yh;
public String toString() {
return String.format("h: %3d,%3d m: %3d,%3d s: %3d,%3d", xh, yh, xm, ym, xs, ys);
}
}
public static ClockCoords coords(int h, int m, int s) {
ClockCoords r = new ClockCoords();
int xcentre = 0;
int ycentre = 0;
r.xs = (int) (Math.cos(s * 3.14f / 30 - 3.14f / 2) * 45 + xcentre);
r.ys = (int) (Math.sin(s * 3.14f / 30 - 3.14f / 2) * 45 + ycentre);
r.xm = (int) (Math.cos(m * 3.14f / 30 - 3.14f / 2) * 40 + xcentre);
r.ym = (int) (Math.sin(m * 3.14f / 30 - 3.14f / 2) * 40 + ycentre);
r.xh = (int) (Math.cos((h * 30 + m / 2) * 3.14f / 180 - 3.14f / 2) * 30 + xcentre);
r.yh = (int) (Math.sin((h * 30 + m / 2) * 3.14f / 180 - 3.14f / 2) * 30 + ycentre);
return r;
}
public static void main(String[] args) throws IOException {
System.out.println(coords(0, 0, 0));
System.out.println(coords(0, 0, 45));
System.out.println(coords(6, 0, 0));
System.out.println(coords(6, 30, 0));
}
which gives me this:
h: 0,-29 m: 0,-39 s: 0,-44
h: 0,-29 m: 0,-39 s: -44, 0
h: 0, 29 m: 0,-39 s: 0,-44
h: -7, 28 m: 0, 39 s: 0,-44
So, if I haven't messed this up, the hour hand is 29 units long, the minute hand is 39 units long, and the second hand is 44 units long. At the start of the day, the first entry, they're all pointing straight up. 45 seconds into the day, the second entry, sees the second hand pointing off to the left, but the other two hands are still point straight up given integer granularity and hands that aren't too long. The third entry, 6:00, just flips the hour hand to point down. The fourth entry is interesting, 6:30, in that it points the minute hand down, but also moves the hour hand a little to the left and up...our first hand in a position not at a 90 degree angle to center. Interesting stuff. As to the WHY of all of this...I assume it's all basic trig and cartesian math.
Wait a sec...there one thing strange I don't get...I see in the formulas where each hand is given a different length. Why are the hand lengths I see off by 1 from what's in the formulas? My guess is that it has to do with the very rough approximation of PI that's used. I think those hands aren't pointing quite straight up. That's all I can think of. Maybe tomorrow I'll try plugging in a better value for PI.
Let me provide you some background information as well.
Trigonometry
is all about a circle, having a radius of 1 unit, centered in the origo, that is, point (0, 0). The coordinates of a point on the circle can be calculated as x = cos(alpha), y = sin(alpha), where alpha is the angle. Since all the points of the circle are of equal distance from the center, you only need to know the angle to compute the coordinates, which are (cos(alpha), sin(alpha)).
Reason: Look at Pythagoras's theorem, which is, by the way, a consequence of the law of cosines, where the largest angle of the triangle is of 90 degree.
Pythagoras's theorem states that
where a, b and c are lengths of sides of the triangle, the triangle being perpendicular and a < c > b is true. So, the cos and sin is due to trigonometrical coordinates.
Radians, PI/2
Units of angle can be measured in degrees (360 degrees being the full circle) or radians (2 PI being the full circle). Let's talk in radians. In math, 0 radians is the angle of the upmost point of the circle. pi/2 is the left-most. pi is the downmost. 3pi/2 is the rightmost. Notice, that as the angle increases your point moves counter-clockwise.
Since this is periodic, it is true that
2 * k * pi + alpha = alpha
On screens, y points downwards, by contrast to the standard in math, where y vertex points upwards. So, if you start from 0 radians, that will be the downmost point when shown on the screen and due to the invert y, as you increase the angle, you move to the clockwise direction. Removing pi / 2 from 0 points you to the rightmost point.
Variables
(xh, yh) are the hour coordinates
(xm, ym) are the minute coordinates
(xs, ys) are the second coordinates
They are the hands of a traditional clock.
h is the hour angle
m is the minute angle
s is the second angle
(xcentre, ycentre) are the coordinates of the center. They might be different from (0, 0), so coordinate moving, the so-called translation is supported.
Step sizes
There are 60 seconds in a minute and there are 60 minutes in an hour, so the angle step needs to be the same for them, even though, the frequency of steps is different, while there are 24 hours in a day, so the angle step of hour needs to be both less frequent and larger (12 positions on a traditional clock).
Length of hands
Hour, minute and second hands (no pun intended) differ in their length, this is why the unit of the trigonometric circle is multiplied by 45, 40 and 30, respectively.
As time passes, presumably the angles are changed and subsequently their coordinates change.
A less-exhaustive explanation, looking only at seconds:
xs = (int)(Math.cos(s*3.14f/30-3.14f/2)*45+xcentre);
ys = (int)(Math.sin(s*3.14f/30-3.14f/2)*45+ycentre);
As Steve's answer notes, drawing a line from (xcentre, ycentre) to (xs, ys) would display a seconds-hand, with "up" being "y = 0" -- so that axis is reversed compare to traditional plots. This actually works in our favor: normally, as angles grow, they are displayed as going anti-clockwise. Since the y axis is reversed in screen coordinates, this is fine for us: our hands will advance clockwise, as expected.
Let us look at the maths, using xs:
xs = Math.cos(s*3.14f/30-3.14f/2)*45; // removed rounding & using xcentre=0
xs = Math.cos((s/30)*PI - PI/2) * sHandLength; // use PI=3.14..., sHandLength=45
Now, at time 0, we want the seconds-hand to look straight up. But normally cos(0) = 1. If we substract 90º (PI/2), it will be looking straight up:
xs = Math.cos((s/30)*PI - zeroIsUp) * sHandLength;
We can undo this to keep on reasoning about the remaining expression:
xs = Math.cos((s/30)*PI); // sHandlength of 1, time 0 is left
All that is missing is that mysterious s/30*PI. Let's make a small table:
seconds(s) radians(argument to Math.cos())
0 0
15 PI/2 -- a quarter-turn of the hand
30 PI -- a half-turn
45 3*PI/2 -- a three-quarters turn
60 2*PI, or 0 -- a full turn
So it seems that it is simply that (s/30) * PI is short for (s/60) * (2*PI).
For a book on Java, I would have expected a much clearer way of writing this. My personal preference would have been:
xs = (int)(Math.cos(base60toRadians(s) - zeroIsUp) * secondHandLength + xCentre);
ys = (int)(Math.sin(base60toRadians(s) - zeroIsUp) * secondHandLength + yCentre);
// ... somewhere else
private float base60toRadians(int b60) { return (b60 / 60) * (2 * Math.PI); }
The coordinates of the clock's centre are (xcentre, ycentre).
With a geometric affine translation to the centre you can calculate like from (0, 0).
The hands are rotating clock wise, in the negative direction.
Now the hands of a clock start at the top, and (0, 1), which has an angle π/2 (90°). (1, 0) being where the angle starts, (-1, 0) halfways having angle π (180°).
The full 360° angle being 2π, 1/60th thereof becomes:
Seconds: 60 seconds = 2π; angle 2π / 60 = π / 30
double startAngle = Math.PI / 2; // Value 0 has angle π/2
double rs = 45;
xs = (int)(Math.cos(-s * Math.PI / 30 - startAngle) * rs + xcentre);
ys = ... sin ...
Hours: 24 hours = 2π; angle 2π / 24 = π / 12
I need a fast way to find maximum value when intervals are overlapping, unlike finding the point where got overlap the most, there is "order". I would have int[][] data that 2 values in int[], where the first number is the center, the second number is the radius, the closer to the center, the larger the value at that point is going to be. For example, if I am given data like:
int[][] data = new int[][]{
{1, 1},
{3, 3},
{2, 4}};
Then on a number line, this is how it's going to looks like:
x axis: -2 -1 0 1 2 3 4 5 6 7
1 1: 1 2 1
3 3: 1 2 3 4 3 2 1
2 4: 1 2 3 4 5 4 3 2 1
So for the value of my point to be as large as possible, I need to pick the point x = 2, which gives a total value of 1 + 3 + 5 = 9, the largest possible value. It there a way to do it fast? Like time complexity of O(n) or O(nlogn)
This can be done with a simple O(n log n) algorithm.
Consider the value function v(x), and then consider its discrete derivative dv(x)=v(x)-v(x-1). Suppose you only have one interval, say {3,3}. dv(x) is 0 from -infinity to -1, then 1 from 0 to 3, then -1 from 4 to 6, then 0 from 7 to infinity. That is, the derivative changes by 1 "just after" -1, by -2 just after 3, and by 1 just after 6.
For n intervals, there are 3*n derivative changes (some of which may occur at the same point). So find the list of all derivative changes (x,change), sort them by their x, and then just iterate through the set.
Behold:
intervals = [(1,1), (3,3), (2,4)]
events = []
for mid, width in intervals:
before_start = mid - width - 1
at_end = mid + width
events += [(before_start, 1), (mid, -2), (at_end, 1)]
events.sort()
prev_x = -1000
v = 0
dv = 0
best_v = -1000
best_x = None
for x, change in events:
dx = x - prev_x
v += dv * dx
if v > best_v:
best_v = v
best_x = x
dv += change
prev_x = x
print best_x, best_v
And also the java code:
TreeMap<Integer, Integer> ts = new TreeMap<Integer, Integer>();
for(int i = 0;i<cows.size();i++) {
int index = cows.get(i)[0] - cows.get(i)[1];
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
index = cows.get(i)[0] + 1;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) - 2);
}else {
ts.put(index, -2);
}
index = cows.get(i)[0] + cows.get(i)[1] + 2;
if(ts.containsKey(index)) {
ts.replace(index, ts.get(index) + 1);
}else {
ts.put(index, 1);
}
}
int value = 0;
int best = 0;
int change = 0;
int indexBefore = -100000000;
while(ts.size() > 1) {
int index = ts.firstKey();
value += (ts.get(index) - indexBefore) * change;
best = Math.max(value, best);
change += ts.get(index);
ts.remove(index);
}
where cows is the data
Hmmm, a general O(n log n) or better would be tricky, probably solvable via linear programming, but that can get rather complex.
After a bit of wrangling, I think this can be solved via line intersections and summation of function (represented by line segment intersections). Basically, think of each as a triangle on top of a line. If the inputs are (C,R) The triangle is centered on C and has a radius of R. The points on the line are C-R (value 0), C (value R) and C+R (value 0). Each line segment of the triangle represents a value.
Consider any 2 such "triangles", the max value occurs in one of 2 places:
The peak of one of the triangle
The intersection point of the triangles or the point where the two triangles overall. Multiple triangles just mean more possible intersection points, sadly the number of possible intersections grows quadratically, so O(N log N) or better may be impossible with this method (unless some good optimizations are found), unless the number of intersections is O(N) or less.
To find all the intersection points, we can just use a standard algorithm for that, but we need to modify things in one specific way. We need to add a line that extends from each peak high enough so it would be higher than any line, so basically from (C,C) to (C,Max_R). We then run the algorithm, output sensitive intersection finding algorithms are O(N log N + k) where k is the number of intersections. Sadly this can be as high as O(N^2) (consider the case (1,100), (2,100),(3,100)... and so on to (50,100). Every line would intersect with every other line. Once you have the O(N + K) intersections. At every intersection, you can calculate the the value by summing the of all points within the queue. The running sum can be kept as a cached value so it only changes O(K) times, though that might not be posible, in which case it would O(N*K) instead. Making it it potentially O(N^3) (in the worst case for K) instead :(. Though that seems reasonable. For each intersection you need to sum up to O(N) lines to get the value for that point, though in practice, it would likely be better performance.
There are optimizations that could be done considering that you aim for the max and not just to find intersections. There are likely intersections not worth pursuing, however, I could also see a situation where it is so close you can't cut it down. Reminds me of convex hull. In many cases you can easily reduce 90% of the data, but there are cases where you see the worst case results (every point or almost every point is a hull point). For example, in practice there are certainly causes where you can be sure that the sum is going to be less than the current known max value.
Another optimization might be building an interval tree.
I want to solve a nonlinear multivariable equation with discrete values like this one:
x*y + z + t - 10 = 0
with constraints:
10 < x < 100
etc..
I am trying to do it with Choco library, but I am a little lost.
I found this code:
// 1. Create a Solver
Solver solver = new Solver("my first problem");
// 2. Create variables through the variable factory
IntVar x = VariableFactory.bounded("X", 0, 5, solver);
IntVar y = VariableFactory.bounded("Y", 0, 5, solver);
// 3. Create and post constraints by using constraint factories
solver.post(IntConstraintFactory.arithm(x, "+", y, "<", 5));
// 4. Define the search strategy
solver.set(IntStrategyFactory.lexico_LB(x, y));
// 5. Launch the resolution process
solver.findSolution();
//6. Print search statistics
Chatterbox.printStatistics(solver);
but I don't understand where I place my equation.
I haven't used this library before, but maybe you should simply treat your equation as a constraint?
Yes, more precisely you should decompose your equations into several constraints:
10 < x < 100
becomes
solver.post(ICF.arithm(x,">",10));
solver.post(ICF.arithm(x,"<",100));
and
x*y + z + t - 10 = 0
becomes
// x*y = a
IntVar a = VF.bounded("x*y",-25,25,solver);
solver.post(ICF.times(x,y,a);
// a+z+t=10
IntVar cst = VF.fixed(10,solver);
solver.post(ICF.sum(new IntVar[]{a,z,t},cst));
Best,
Contact us for more support on Choco Solver : www.cosling.com
Example 1:
Shop selling beer, available packages are 6 and 10 units per package. Customer inputs 26 and algorithm replies 26, because 26 = 10 + 10 + 6.
Example 2:
Selling spices, available packages are 0.6, 1.5 and 3. Target value = 5. Algorithm returns value 5.1, because it is the nearest greater number than target possible to achieve with packages (3, 1.5, 0.6).
I need a Java method that will suggest that number.
Simmilar algorithm is described in Bin packing problem, but it doesn't suit me.
I tried it and when it returned me the number smaller than target I was runnig it once again with increased target number. But it is not efficient when number of packages is huge.
I need almost the same algorithm, but with the equal or greater nearest number.
Similar question: Find if a number is a possible sum of two or more numbers in a given set - python.
First let's reduce this problem to integers rather than real numbers, otherwise we won't get a fast optimal algorithm out of this. For example, let's multiply all numbers by 100 and then just round it to the next integer. So say we have item sizes x1, ..., xn and target size Y. We want to minimize the value
k1 x1 + ... + kn xn - Y
under the conditions
(1) ki is a non-positive integer for all n ≥ i ≥ 1
(2) k1 x1 + ... + kn xn - Y ≥ 0
One simple algorithm for this would be to ask a series of questions like
Can we achieve k1 x1 + ... + kn xn = Y + 0?
Can we achieve k1 x1 + ... + kn xn = Y + 1?
Can we achieve k1 x1 + ... + kn xn = Y + z?
etc. with increasing z
until we get the answer "Yes". All of these problems are instances of the Knapsack problem with the weights set equal to the values of the items. The good news is that we can solve all those at once, if we can establish an upper bound for z. It's easy to show that there is a solution with z ≤ Y, unless all the xi are larger than Y, in which case the solution is just to pick the smallest xi.
So let's use the pseudopolynomial dynamic programming approach to solve Knapsack: Let f(i,j) be 1 iif we can reach total item size j with the first i items (x1, ..., xi). We have the recurrence
f(0,0) = 1
f(0,j) = 0 for all j > 0
f(i,j) = f(i - 1, j) or f(i - 1, j - x_i) or f(i - 1, j - 2 * x_i) ...
We can solve this DP array in O(n * Y) time and O(Y) space. The result will be the first j ≥ Y with f(n, j) = 1.
There are a few technical details that are left as an exercise to the reader:
How to implement this in Java
How to reconstruct the solution if needed. This can be done in O(n) time using the DP array (but then we need O(n * Y) space to remember the whole thing).
You want to solve the integer programming problem min(ct) s.t. ct >= T, c >= 0 where T is your target weight, and c is a non-negative integer vector specifying how much of each package to purchase, and t is the vector specifying the weight of each package. You can either solve this with dynamic programming as pointed out by another answer, or, if your weights and target weight are too large then you can use general integer programming solvers, which have been highly optimized over the years to give good speed performance in practice.
So I recently was introduced to Points in my class. Right now I am trying to find the difference of X and then the difference of Y and then add them together. I am so lost and cant quite find the right answer. What are some options for this?
Just a heads up this is using the Point class.
Better put I dont understand the Point class that I was taught in my AP Computer Science class. Not that I don't understand how to subtract x2-x1. What command would I use to accomplish this because I continue to get errors when typing x2-x1.
Heres is what I am supposed to do:
"In our case, the Manhattan distance is the sum of the absolute values of the differences in their coordinates; in other words, the difference in x plus the difference in y between the points."
Exact words from teacher.
Difference of two X points? If so, you would do X1-X2...same with Y points... Y1-Y2.
To make sure the difference is positive, you can do
Math.abs(p.X1-p.X2)
likewise...
Math.abs(p.Y1-p.Y2)
then just add them together...
Math.abs(p.X1-p.X2) + Math.abs(p.Y1-p.Y2)
After your clarifications...I have revised my answer
public int manhattanDistance(Point other){ //not sure why return an int...I think returning a double makes more sense..
int xdist = Math.abs(this.x-other.x);
int ydist = Math.abs(this.y-other.y);
return (int)xdist+ydist; //cast to int because you must return int
}
or less code version...
public int manhattanDistance(Point other){
return (int)Math.abs(this.x-other.x) + Math.abs(this.y-other.y);
}
The distance between two points (in a straight line) can be calculated as:
___________________________
/ 2 2
/ (p2x - p1x) + (p2y - p1y)
v
For example, the classic 3-4-5 triangle:
4
+---*
| /
3 | / 5
|/
*
The hypotenuse (5) can be calculated as the square root of 3 * 3 + 4 * 4.
One way you would do that with two Point objects in Java would be with:
dist = (point2.x - point1.x) * (point2.x - point1.x)
+ (point2.y - point1.y) * (point2.y - point1.y);
though you could also use Math.pow(something,2) in place of the multiplications.
If on the other hand you wanted to find the Manhattan distance (as now seems evident by the extra information added to the question), you would use something like:
mdist = Math.abs (point2.x - point1.x) + Math.abs (point2.y - point1.y);
This works out the X difference (which may be negative) then takes the absolute value of that to force it to positive. Then it does the same with the Y difference and adds them together.