Algorithm - Find point with minimum distance travelled - javascript

This algorithm is to find the best point to meet, such that the distance travelled by all people is minimum.
To elaborate -
Consider the below line, an x-axis with each person in different point to the 0th position(imagine x-y axis). Each point denotes the distance he is from 0th position.
|
---30-------15-----10--------5----0----6-----------20-----------40-----50--
|
Now Find come up with an algorithm to find the point where each person has to travel and get together such that the total distance travelled is minimum.
Note - I thought of finding median/average, does not work always.
How about choosing nearest point to 0th position? Again not always.
Any ideas guys?

Assuming that all positions are in one dimension (i.e. along one axis only), optimal solution is median of all positions.
The median is defined such that half the values are larger than, and half are smaller than, the median. If elements in the sample data increase arithmetically, when placed in some order, then the median and arithmetic average are equal. For example, consider the data sample {1,2,3,4}. The average is 2.5, as is the median. However, when we consider a sample that cannot be arranged so as to increase arithmetically, such as {1,2,4,8,16}}, the median and arithmetic average can differ significantly. In this case, the arithmetic average is 6.2 and the median is 4. In general, the average value can vary significantly from most values in the sample, and can be larger or smaller than most of them.
Source: https://en.wikipedia.org/wiki/Arithmetic_mean
In above example,
total distance with average value (6.2) as solution = 23.2
total distance with median value (4) as solution = 21, which of course is the lower distance, hence optimal solution

Related

Efficient algorithm for finding which hexagon a point belongs to

I'm trying to find a more efficient way of determining which hexagon a point belongs to from the following:
an array of points - for the sake of argument, 10000 points.
an array of center points of hexagons, approximately 1000 hexagons.
every point will belong to exactly one hexagon, some (most) hexagons will be empty.
The hexagons form a perfect grid, with the point of one hexagon starting in the top left corner (it will overlap the edge of the total area).
My current solution works, but is rather slow n * (m log m) I think, where n=length(points) and m=length(hexagons).
I suspect I can do much better than this, one solution that comes to mind is to sort (just once) both the points and the hexagons by their distance to some arbitrary point (perhaps the middle, perhaps a corner) then iterate over the points and over a subset of the hexagons, starting from the first hexagon whose distance to this point is >= to the last hexagon matched. Similarly, we could stop looking at hexagons once the distance difference between the (point -> ref point) and (hexagon center -> ref point) is larger than the "radius" of the hexagon. In theory, since we know that every point will belong to a hexagon, I don't even have to consider this possibility.
My question is: Is there a Much better way of doing it than this? In terms of complexity, I think it's worst case becomes marginally better n * m but the average case should be very good, probably in the region of n * 20 (e.g., we only need to look at 20 hexagons per point). Below is my current inefficient solution for reference.
points.forEach((p) => {
p.hex = _.sortBy(hexes, (hex) => {
const xDist = Math.abs(hex.middle.x - p.x);
const yDist = Math.abs(hex.middle.y - p.y);
return Math.sqrt((xDist * xDist) + (yDist * yDist));
})[0];
});
For an arbitrary point, you can find the nearest hexagon center in two steps (assuming the same arrangement as that of Futurologist):
divide the abscissa by the horizontal spacing between the centers, and round to the nearest integer.
divide the ordinate by the half of the vertical spacing, and round to the nearest even or odd integer, depending on the parity found above.
consider this center and the six ones around it, and keep the closest to the target point.
This gives you the indexes of the tile, in constant time.
Just a suggestion: assume you have the centers of each regular hexagon from your regular hexagonal grid (if I have understood correctly, that's part of the information you have).
-----
/ \
- ----- -----------> x - axis
\ / \
----- -
/ \ /
- -----
\ / \
----- -
| \ /
| -----
|
|
V
y - axis
You can think that your coordinate system starts from the center of the hexagon in the upper left corner and the y coordinate axis runs vertically down, while the x axis runs from left to right horizontally. The centers of the hexagons from your regular hexagonal grid form an image of the regular square grid, where the integer vertices of the square grid are transformed into the centers of the polygons by simply multiplying the coordinates of points in the square grid by the 2 x 2 square matrix (a sheer metrix)
A = a*[ sqrt(3)/2 0;
1/2 1 ]
where a is a parameter of the hexagonal grid, the distance between the centers of two edge-adjacent hexagons. This provides a way to assign integer indices [m n] to the grid formed by the hexagonal centers. After that, if you are given a point with coordinates [x y] in the hexagonal grid, you can apply the inverse matrix of A
[u; v] = A^(-1)*[x; y]
where
A^(-1) = (2/(a*sqrt(3)))*[ 1 0 ;
-1/2 sqrt(3)/2 ]
([x; y] and [u; v] are column vectors) and then take m = floor(u) and n = floor(v) to determine the integer coordinates (also the indices) [m = floor(u), n = floor(v)] of the upper left corner of the square cell from the square grid (observe that we have chosen the coordinates for both grids to start from the upper left corner). Thus, your point [u, v] is in the square with vertices [m,n] [m+1, n] [m, n+1] [m+1, n+1]
which means that the original point [x y] is in one of the four hexagons whose centers have indices [m,n] [m+1, n] [m, n+1] [m+1, n+1]. So you can use that to check in which of the four hexagons the point [x y] is.
I hope this helps.
Update: Leaving the below comment for posterity
I am now using the code provided here: https://www.redblobgames.com/grids/hexagons/
A really important note, is that your hexagon grid MUST start with the first hexagons mid point at (0, 0) - if it doesn't you get extremely odd results from this, which at first glance appeared as rounding errors (even after accounting for the expected offset). For me, it didn't matter where the first hexagon was positioned, so I just set it to be (0, 0) and it worked great.
Old solution
I'm still hoping for an optimal solution, but I ended up rolling my own which needs only check 6 hexagons per point, with a little overhead (approximately sqrt(m)) needed in addition.
With approximately 3000 points, and 768 hexagons (of which 310 were populated), it correctly assigned the point to the hexagon 100% of the time (as checked against a brute force approach) and took 29 milliseconds, compared to ~840 with brute force.
To start with, I store the hexagons in a map where the key is "${column},${row}". The columns technically overlap, so for the 0th row, the 0th column starts at -0.5 * hexWidth, and for row 1, the 0th column starts at 0px.
Next, I start from the position of the top left hexagon, item "0,0", which should also be at position 0, and increment y by either the height of the hexagon, or the edge length of the hexagon accordingly. When the y is > the points y, I've found the probable row, I then check the row above and below.
For the column within the row, I take the both the Math.floor and Math.ceil of x / hexWidth.
Doing this gives 6 hexagons to check, from this point the solution is identical to the solution in the question.
In theory, this could be used to just look up the correct hexagon, using the x/y position. However in practice, this didn't work for me about 5% of the time with off by 1 errors, likely a rounding problem.
Some other things I looked at:
As suggested by #jason-aller, https://www.redblobgames.com/grids/hexagons/#rounding. Unfortunately, this seems to assume some form of transformation on the hex grid (rotations) and is not easy to follow - continually referencing functions which have yet to be defined.
QuadTree (various implementations) unfortunately, this returned approximately 100 "potential matches" for each point - so the performance improvement was not good. I'm aware that insertion order changes how useful QuadTree is, I tried natural order, sorted by distance from top, left and shuffled, they all performed equally badly. It's likely that an optimal solution with QuadTree would involve populating the tree with the item closest to the mid point, then the items 1/2 from the mid point to each corner, recursively. Too much like hard work for me!

Cheaply determine which of 2 Bezier Curves is longer

In my situation I need to compare the length of 2 bezier curves. I do not need to compute the actual length of either curve. I merely want to cheaply compare which of the 2 is longer. My assumptions for this method are as followed:
Both Bezier curves to compare are same dimension(number of control points)
The dimension of the curves could be any number greater than 2
I need to output which of the 2 curves is longer (either if equal)
My original thought, was to just add the lengths of control points ie:
distance(p0, p1) + distance(p1, p2) + distance(p2, p3)...
And It seems to work decently for lower order bezier curves. However I sure that this would not scale well in higher order curves.
I ended with a solution that adds the distance between each control point projected on the curve(basically take number of control points / index of point and using that value as T), and seems to work on some higher dimension curves.
I can't imagine I am the first person to want to do this, So to reiterate does anyone know of the right way to do this?

Concept of a sript to calculate mouse velocity

Hi guys:)Could someone explain me this code?I am trying to understand but there is nothing to do.Why this line of code?
Math.sqrt(x_dist*x_dist+y_dist*y_dist)/interval;
Isn't sufficent this?
x_dist+y_dist/interval;
I don't understand the concept of this code...
https://jsfiddle.net/vnodkumar1987/ER8qE/
The first example calculates the hypotenuse, and in so doing achieves an absolute velocity value of the mouse vector.
The second example will give a bad result unless both x_dist and y_dist are positive. In other words, if you were moving down and left, or up and right, the second example would have a subtractive effect, and not represent the true overall velocity. In the case of up and left, the velocity would not only be proportionately incorrect (only useful for comparison purposes), but also result negative sign that you would have to account for. (I am assuming 0,0 represents the upper left of the mouse-able area and x_max,y_max to be the lower right.)
The Math.sqrt may not be necessary if you are just scaling proportionate velocity, but it certainly is if you want to know true pixels/interval. You would also have to take into account how big a variable container you are working with, but I'm sure it would all fit into a double... unless you were looking for extreme precision.
Imagine you travel in a straight line so that you end up at a point 3 miles West, and 4 miles South in exactly 1 hour. The velocity answer is not 3+4=7 miles per hour, nor is it-3+4=1 miles per hour. The correct answer of absolute velocity is the hypotenuse, which would be 5 mph. sqrt(west^2+south^2)
Example #1 would be the proper code. Example #2 could be roughly used if you can ignore the sign, and you needed the code to execute very quickly.
The velocity is distance_travelled/time_taken.
Say the pointer moves from (x1,y1) to (x2,y2) as shown in the figure above. The distance travelled is not the sum of the x and y distances.
Summing up x and y assumes that the pointer went from (x1,y1) to (x2,y1) and then from (x2,y1) to (x2,y2). i.e. the sum of the lengths of the 2 blue lines. But what you need is the length of the black line.
The actual distance travelled is d as shown in the figure. Using Pythagorean theorem, d^2 = x_dist^2 + y_dist^2.
Which leaves you with the line of code you have in the question for the speed
Math.sqrt(x_dist*x_dist+y_dist*y_dist)/interval;
You are making a pythagorean triangle with the two catethus being x_dist and y_dist, which are the distance the mouse moved in each of X and Y axis each frame. What that line of code does is to get the magnitude of the delta position vector of the mouse and divide it by some scalar value.
Also, note that sqrt(a^2 + b^2) does NOT equal a + b.
EDIT: Not velocity, but delta position.

Generate random 5d vector of given magnitude

Given a five dimensional space, I would like to generate 100 vectors, all with a fixed magnitude=M, where the components values are randomly distributed.
I was originally thinking of starting off with a unit vector and then applying a rotation matrix, with random parameters for the 10 degrees of freedom ... Would this work? and how?
Any nice way of doing this in Javascript...?
cheers for any pointers!
Here is the Monte Carlo algorithm that I would use (I do not know Javascript well enough to code in it off the top of my head):
Generate random values in the range from -1 to 1 for each of the five dimensions.
Calculate the Magnitude M, if M=0 or M>1 then reject these values and return to step #1.
Normalize the vector to have a Magnitude of 1 (divide each dimension by M).
That should give you random unit vectors evenly distributed over the 5-dimensional super-sphere surface.
The question has been asked: "Why reject the vector if M>1?"
Answer: So that the final vectors will be uniformly distributed across the surface of the unit 5-sphere.
Reasoning: What we are generating in the first step is a set of random vectors that are uniformly distributed within the volume of the unit 5-cube. Some of those vectors are also within the volume of the unit 5-sphere and some of them are outside of that volume. If normalized, the vectors within the 5-sphere are evenly distributed across its surface, however, the ones outside it are not at all evenly distributed.
Think about it like this: Just as with a normal 3-dimensional Unit Cube and Unit Sphere, or even the Unit Square and the Unit Circle, the Unit 5-Sphere is wholly contained within the Unit 5-Cube, which touches only at the five positive unit dimension axis points:
(1,0,0,0,0)
(0,1,0,0,0)
(0,0,1,0,0)
(0,0,0,1,0)
(0,0,0,0,1)
and their corresponding negative unit axis points. This is because these are the only points on the surface of the cube that have a magnitude (distance from the origin) of 1, at all other points, the 5-cube's surface has a distance from the origin that is greater than 1.
And this means that there are many more points between (0,0,0,0,0) and (1,1,1,1,1) than there are between (0,0,0,0,0) and (1,0,0,0,0). In fact about SQRT(5) or aprx. 2.25 times more.
And that means that if you included all of the vectors in the unit 5-cube, you would end up with more than twice as many results "randomly" mapping to about (0.44,0.44,0.44,0.44,0.44) than to (1,0,0,0,0).
For those who are challenging (without foundation, IMHO) that this results in a uniform distribution across the surface of the 5-D Sphere, please see the alternative method in this Wikipedia article section: https://en.wikipedia.org/wiki/N-sphere#Uniformly_at_random_on_the_(n_%E2%88%92_1)-sphere
The problem with sampling from a unit hypercube in 5-dimeensions and then re-scaling, is points in some directions (towards the corners of the hypercube) will be over sampled.
But if you use a rejection scheme, then you lose too many samples. That is, the volume of a unit hypercube in 5-d is pi^2*(8/15) = 5.26378901391432. Compare that to the volume of a unit hyper-cube in 5 dimensions that will just contain the sphere. That hypercube has volume 32. So if you reject points falling outside the sphere, you will reject
1 - 5.26378901391432/32 = 0.835506593315178
or roughly 83.5% of the points get rejected. That means you will need to sample roughly 6 points on average before you do find a sample that is inside the 5-sphere.
A far better idea is to sample using a unit normal sample, then rescale that vector of points to have unit norm. Since the multi-variate normal distribution is spherically symmetric, there is no need for rejection at all.
Here are some approaches, it is for unit vectors but you can just multiply by M:
http://burtleburtle.net/bob/rand/unitvec.html
I'd recommend assigning random numbers between -1 and +1 for each element. Once all elements for a vector have been assigned, then you should normalize the vector. To normalize, simply divide each element by the magnitude of the overall vector. Once you've done that, you've got a random vector with a magnitude of 1. If you want to scale the vectors to magnitude M, you just need to multiply each element by M.
Picking without rejections (6 times faster)
From Mathworld and a link posted by Bitwise:
If you choose n numbers with a normal distribution, treat those as coordinates, and normalize the resulting vector into a unit vector, this chooses a uniformly distributed unit vector in n dimensions. - Burtleburtle (ht Bitwise)
As Bitwise points out, that should be multiplied by the desired magnitude.
Note that there is no rejection step here; the distributions themselves have dealt with the necessary bias towards zero. Since the normal distribution and a semi-circle are not the same shape, I wonder if RBarryYoung's answer really gives a uniform distribution on the surface of the sphere or not.
Regarding uniform hypercube picking with hypersphere rejection (RBarryYoung's answer)
The Mathworld article includes a description of using 4 random numbers picked from uniform distributions to calculate random vectors on the surface of a 3d sphere. It performs rejection on the 4d vector of random numbers of anything outside the unit hypersphere, as RBarryYoung does, but it differs in that it (a)uses an extra random number and (b)performs a non-linear transform on the numbers to extract the 3d unit vector.
To me, that implies that uniform distributions on each axis with hypersphere rejection will not achieve a uniform distribution over the surface of the sphere.

Could you use Html 5 canvas to calculate the distance you travelled along a river?

My thought was that you could draw a line that traversed the river and then if you knew the total distance of the river you divide the line's pixel length by the distance.
So if your line was 760px and the distance of the river was 20 miles then 760 / 20 = 38px = 1 mile.
Of course if my line was just a straight line or a series of lines this would be fairly simple. However, I would like my line to reflect the contours of the river and as such would be curved in places.
Firstly, is this a good method for plotting distance travelled along a river? If not what would work better (i have a feeling my maths is wrong!).
If this is a good method how would i take into account the curved nature of the line and how this might affect the pixel length of the line?
Calculating the length of a river is similar to calculating the Length of an Arc
.
Even if you draw the river exactly as you want it in an canvas(or in any Raster Image for that matter), and then count the amount of blue pixels, you would only be able to get an approximate answer as close as canvaswidth / riverdistance.
I wouldn't use miles (because its too crude). Use something shorter instead (I'd use meters, but ymmv).
Then just draw a line along the curvature of the river and count the pixels of that line, every pixel represents a given distance. (e.G. one pixel could represent 150 meters)

Categories

Resources