Algorithm to find a frontline between enemy and friendly bases? - algorithm

Please look at this picture first:
As you can see, blue and red both have a line showing the frontline bases.
Let's assume two players start playing against eachother.
One placing a base at the far left, the other at the far right.
The players continue by expanding and gaining territory.
After a while, the two sides will meet and battle will start.
Question is, in a randomly ordered list of base positions how would one find the two lines that are drawn in the picture?

You could get the distance between enemy bases, where the distance is shorter is the frontline.
Example:
0 1 2 3 4 5 6
0 aa A B bbb
1 aA B bb
2 A B b
3 aA B b
4 aaaA Bb
5 aaaA B
6 aaaA B
If you substract the X positions of the enemy bases in the same row, the ones with the less distance between them are the front lines, B.x - A.x will give you a smaller number that b.x - a.x. Then you can check which ones were the ones that gave you the smaller distance for each row.
Unless I'm getting your question wrong.

area
many games do not draw territory border by polylines
instead they draw a disc with constant radius (or dependent on base strength) at every base position
if the radius is set big enough then these discs/circles will overlap
and create seamless area of single color representing controlled territory
it is easy but inaccurate
perimeter polyline
first cluster all bases and create lists of bases close together
this can be done by grouping bases with distance <= treshold
process each group
find the outer most bases of group
something like perimeter points
this may help with it
also it contains inverse problem of yours which can solve the whole thing more here
now find the perimeter closed loop of area
the algorithm for that is also in the link above
when done then use this list of points as BEZIER cubics poly-curve control points
if borderline too close to the bases then enlarge the points
first compute avg point ap of group
then any point p is computed p=((p-ap)*scale)+ap
it is not exact but for your purposes it is enough
if you want something better then
p=p-ap
l=|p|
p=ap+(p*(l+dl)/l)
where dl is the step at which your border is enlarged
and if you want the accurate thing then you have to compute polygon enlargement
which is not easy task
handle edge cases
for singular base groups draw circle around
this approach has problem in close proximity of bases
one solution is not to count bases too close to any enemy base
per pixel borders
you can process the map image by pixels
something like this: (beware this is not tested)
per each pixel
compute the min distance to any player bases
remember two closest distances of different players
distance0 is closest
distance1 is second closest (but base owns another player)
select territory ownership
the player which has closest base own this
if the distance0 > treshold then this area is uncontrolled
in that case stop processing this pixel
if ((distance0 >= d-w)&&(distance0 <= d+w)&&(distance1>d+w+s)) then set pixel color to border polyline color
d is border line distance from base
w is half-size of borderline thickness
s is min distance between close front lines
edge case
previous step ignore border points that are closer to bases (close enemy bases)
to add them just add
if ((distance0<d)&&(|distance0-distance1|<=s+w)&&(|distance0-distance1|>=s-w)) then set pixel color to player ownership
also this will fail if any two opposing bases are closer then s-w
[Notes]
I think the best way is the per pixel
it is most close to the solution you want
the render can be a bit slower but you need to change it only if any base is conquered

Related

Counting number of ways to make a 3 Partition of n dots in a triangle such that each partition fit in a "Y" shape. (More description below)

I want to find an algorithm to tackle this problem but I have no idea what this problem is even called so I can't google it.
Problem:
There is a triangle, and inside the triangle there are n dots. For example, as below.
Now assume 3 sides of triangle are rubber bands and dots are nails on the wall. We tuck each rubber bands into some dot(s). But each rubber bands must be convex towards the center of triangle.
Also, there should be no intersection of any 2 rubber bands apart from the 3 vertices of original triangle.
Also, there should not be any remaining dot inside the polygon formed by 3 rubber bands.
How many valid arrangement of rubberbands, such that all given conditions are satisfied, are there?
Here, in this picture, the leftmost picture is the original state, 2nd picture is a valid composition, 3rd is invalid since blue and red rubber bands intersect, 4th is invalid since there is a nail remaining inside red-blue-green polygon
My approach: After some thoughts: I guessed that if we pick an arbitrary location inside the triangle which is not one of the given dots(nails), and then we make a Y shape starting from that location towards 3 vertices of outer triangle, that is guaranteed to make a unique valid arrangement of rubber bands, if we imagine that each pair of 2 neighboring edges of Y shape is a rubberband and then we release those bands. They will sort themselves out to form a valid arrangement with elasticity.
So from each 3 vertices of triangle, I draw a line towards all n dot(nails). And then for each polygon partitions that are created by those lines and/or 3 sides of triangle(approx n^3 polygon partitions in total), I can make exactly 1 valid composition by picking any point in the polygon and making Y shape.
For example, if I pull rubber bands to form a y-shape as in the left picture, I can then make a valid composition by releasing those rubber bands, as in the right picture.
However, the problem is that 2 or more polygons may yield same valid composition, so we will count more than the correct answer.
For example, if there are only 2 dots(nails), we could make a bunch of polygon partitions by connecting lines(colored brown) starting from each 3 vertices of triangle to 2 dots(nails). so there are 17 partitions. each 17 partitions would yield a valid composition but the answer would be 6. (3 cases where 2 dots go under same rubber band, 3 cases where 1 dot goes under a band and the other dot goes under the other band.)
So I drew several small examples and tried to figure out a pattern to make an algorithm to de-duplicate it and I kind of see a pattern but can't really formulate it into a pseudo code. Any help is appreciated.

Trapping rain water ii (LeetCode) with hole (0)

https://leetcode.com/problems/trapping-rain-water-ii/
Given an m x n matrix of positive integers representing the height of
each unit cell in a 2D elevation map, compute the volume of water it
is able to trap after raining.
A slight addition is if there's a hole in it and whole platform is in air? How much can it actually store?
While i can look for bounding region around the hole and calculate how much water is wasted there, i can only define a rectangular bounding region (Case 1), but for the second case how can you locate and calculate water in this region:
If i just look for rectangular region which consists the bounding region defined by grey lines, calculate water stored in here then subtract from total, water stored in green region will be removed which shouldn't be. And the bigger problem what if it doesn't exist at all?
Or is there any approach i'm missing, any and all suggestions are welcome.
Here’ the approach that worked for me.
I was looking at separate cells, not regions.
Let a[i][j] be the total height of combined stone (or whatever material is it) and water above it.
Then we have:
a[i][j] = max(height[i][j], min(a[i+1][j], a[i][j+1], a[i-1][j], a[i][j-1]))
The “max” part is to prevent the value from being less than the stone part. And the “min” part is to make sure that water is held by the adjacent cells.
For boundaries the water level is zero so a[i][j] = height[i][j]. For other cells we can start with a very big number.
To illustrate this a little bit: suppose you know for sure that the water level for an adjacent cell can't be more than 7 (for example). Then the water level for your current cell also can't be more than 7: there's literally nothing to hold the water from flowing in direction of that adjacent cell.
By the way, if you have a "hole" in a cell then a[i][j] = 0 since no water can be accumulated there.
We can repeatedly apply that formula as kind of “relaxation” until it’s no longer possible. When it’s no longer possible we have our final configuration and we just need to calculate the water volume.
For procedure to be efficient we can go from top to bottom applying:
a[i][j] = max(height[i][j], min(a[i-1][j], a[i][j-1]))
and then from bottom to top applying:
a[i][j] = max(height[i][j], min(a[i+1][j], a[i][j+1]))
repeating it again an again while at least one cell value changes.

How to find the pixel that is farthest from another in the same pixel group

By "Group", I mean a set of pixels such that every pixel at least have one adjacent pixel in the same set, the drawing shows an example of a group.
I would like to find the pixel which is having the greatest straight line distance from a designated pixel (for example, the green pixel). And the straight line connecting the two pixels (the red line) must not leave the group.
My solution is looping through the degrees and simulating the progress of the lines starting from the green pixel with the degree and see which line travelled the farthest distance.
longestDist = 0
bestDegree = -1
farthestX = -1
farthestY = -1
FOR EACH degree from 0 to 360
dx=longestDist * cos(degree);
dy=longestDist * sin(degree);
IF Point(x+dx , y+dy) does not belong to the group
Continue with next degree
//Because it must not be the longest line, so skip it
END IF
(farthestX , farthestY) = simulate(x,y,degree)
d = findDistance(x , y , farthestX , farthestY)
IF d > longestDist
longestDist = d
bestDegree = degree
END IF
END FOR
It is obviously not the best algorithm. Thus I am asking for help here.
Thank you and sorry for my poor English.
I wouldn't work with angles. But I'm pretty sure the largest distance will always be between two pixels at the edge of the set, thus I'd trace the outline: From any pixel in the set go to any direction until you reach the edge of the set. Then move (couter)clockwise along the edge. Do this with any pixel as starting point and you'll be able to find the largest distance. It's still pretty greedy, but I thought it might give you an alternative starting point to improve upon.
Edit: What just came to my mind: When you have a start pixel s and the end pixel e. In the first iteration using s the corresponding e will be adjacent (the next one along the edge in clockwise direction). As you iterate along the edge the case might occur, that there is no straight line through the set between s and e. In that case the line will hit another part of the set-edge (the pixel p) though. You can continue iteration of the edge at that pixel (e = p)
Edit2: And if you hit a p you'll know that there can be no longer distance between s and e so in the next iteration of s you can skip that whole part of the edge (between s and p) and start at p again.
Edit3: Use the above method to find the first p. Take that p as next s and continue. Repeat until you reach your first p again. The max distance will be between two of those p unless the edge of the set is convex in which case you wont find a p.
Disclaimer: This is untested and are just ideas from the top of my head, no drawings have been made to substantiate my claims and everything might be wrong (i.e. think about it for yourself before you implement it ;D)
First, note that the angle discretization in your algorithm may depend on the size of the grid. If the step is too large, you can miss certain cells, if it is too small, you will end up visiting the same cell again and again.
I would suggest that you enumerate the cells in the region and test the condition for each one individually instead. The enumeration can be done using breadth-first or depth-first search (I think the latter would be preferable, since it will allow one to establish a lower bound quickly and do some pruning).
One can maintain the farthest point X found so far and for each new point in the region, check whether (a) the point is further away than the one found so far and (b) it's connected to the origin by a straight line passing through the cells of the region only. If both conditions are satisfied, update the X, else go on with the search. If condition (a) is not satisfied, condition (b) doesn't have to be checked.
The complexity of this solution would be O(N*M), where N is the number of cells in the region and M is the larger dimension of the region (max(width,height)). If performance is of essence, more sophisticated heuristics can be applied, but for a reasonably sized grid this should work fine.
Search for pixel, not for slope. Pseudocode.
bestLength = 0
for each pixel in pixels
currentLength = findDistance(x, y, pixel.x, pixel.y)
if currentLength > bestLength
if goodLine(x, y, pixel.x, pixel.y)
bestLength = currentLength
bestX = pixel.x
bestY = pixel.y
end
end
end
You might want to sort pixels descending by |dx| + |dy| before that.
Use a double data-structure:
One that contains the pixels sorted by angle.
The second one sorted by distance (for fast access, this should also contain "pointers" for the first data structure).
Walk through the angle sorted one, and check for each pixel that the line is within the region. Some pixels will have the same angle, so you can walk from the origin along the line, and go till you go out from the region. You can eliminate all the pixels which are beyond that point. Also, if the maximum distance increased, remove all pixels which have a shorter distance.
Treat your region as a polygon instead of a collection of pixels. From this you can get a list of line segments (the edges of your polygon).
Draw a line from your start pixel to each pixel you are checking. The longest line that does not intersect any of the line segments of your polygon indicates your most distant pixel that is reachable by a straight line from your pixel.
There are various optimizations you can make to this and a few edges cases to check, but let me know if you understand the idea before i post those... in particular, do you understand what I mean by treating as a polygon instead of a collection of pixels?
To add, this approach will be significantly faster than any angle based approach or approach that requires "walking" for all but the smallest collections of pixels. You can further optimize because your problem is equivalent to finding the most distant endpoint of a polygon edge that can be reached via an unintersected straight line from your start point. This can be done in O(N^2), where N is the number of edges. Note that N will be much much smaller than the number of pixels, and many of the algorithms proposed that use angles an/or pixel iteration are be going to instead depend on the number of pixels.

Hungarian Rings Puzzle

I'm having a hard time finding an admissible heuristic for the Hungarian Rings puzzle. I'm planing on using IDA* algorithm to solve and am writing the program in Visual Basic. All I am lacking is how to implement the actual solving of the puzzle. I've implemented both the left and right rings into their own arrays and have functions that rotate each ring clockwise and counterclockwise. I'm not asking for code, just somewhere to get started is all.
Here is the 2 ring arrays:
Dim leftRing(19) As Integer
' leftRing(16) is bottom intersection and leftRing(19) is top intersection
Dim rightRing(19) As Integer
' rightRing(4) is top intersection and rightRing(19) is bottom intersection
In the arrays, I store the following as the values for each color:
Red value = 1 Yellow = 2 Blue = 3 and Black = 4
I suggest counting "errors" in each ring separately - how many balls need to be replaced to make the ring solved (1 9-color, 1 10-color, one lone ball from a 9-color). At most two balls can be fixed using a rotation, then another rotation is needed to fix another two. Compute the distance of each ring individually = 2n-1 where n is half the amount of bad positions and take the larger of them. You can iterate over all twenty positions when looking for one that has the least amount of errors, but I suppose there's a better way to compute this metric (apart from simple pruning).
Update:
The discussion with Gareth Reed points to the following heuristic:
For each ring separately, count:
the number of color changes. The target amount is three color changes per ring, and at most four color changes may be eliminated at a time. Credits go to Gareth for this metric.
the count of different colors, neglecting their position. There should be: 10 balls of one 10-color, 9 balls of one 9-color and one ball of the other 9-color. At most 2 colors can be changed at a time.
The second heuristic can be split into three parts:
there should be 10 10-balls and 10 9-balls. Balls over ten need to be replaced.
there should be only one color of 10-balls. Balls of the minor color need to be replaced.
there should be only one ball of a 9-color. Other balls of the color need to be replaced. If all are the same color, and 9-color is not deficient, one additional ball need to be replaced.
Take the larger of both estimates. Note that you will need to alternate the rings, so 2n-1 moves are actually needed for n replacements. If both estimates are equal, or the larger one is for the latest moved ring, add an additional one. One of the rings will not be improved by the first move.
Prune all moves that rotate the same ring twice (assuming a move metric that allows large rotations). These have already been explored.
This should avoid all large local minima.

Calculating Area Between Sprites

I am working on a simple 2D soccer game, while passing the ball between my players I would like to check if any of the enemy players can intercept the ball, what I would like to do is calculate a list of coordinates between my players a corridor so to speak and then check if any enemy players are in this region,
--------------------------
S S
--------------------------
It is easy to calculate the area between Ss when they lie like this, but how do I calculate the region when they are not aligned,
/S /
/ /
/ /
/ /
/ /
/ /
/ S/
EDIT: When I mean area, I want the list of coordinates in that region so that I can check those coordinates against players coordinates, not the magnitude of the area.
(image) http://img441.imageshack.us/img441/9051/soccer.png
Show enemy is between red lines: Calculate the distance of the enemy to the line formed by the two players (dotted line). If it is <= w/2 (w is the width of your "region"), then either the enemy is within the region, or behind one of the players.
Show enemy is between orange lines: To check that he is not behind one of the players, just check that he is between the two lines which pass through one of the players and are normal (perpendicular) to the first line (the dotted line passing through both players).
This will tell you if the enemy is within the yellow region:
Why don't you rotate your coordinate system, so that both players will be aligned?
Assuming you have a fixed number of players (22 for examples) you multiply each of their (x,y) coordinate in the rotation+translation matrix that makes S1 (or S2, doesn't really matters) aligned with its companion.
And you can calculate the rotation matrix from this simple formula:
http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_given_an_axis_and_an_angle
Further explanation and a good example:
http://www.quantunet.com/flash8/knowledgebase/actionscript/advanced/matrix/matrix_rotation.html
If it only needs to be approximate, and you need to calculate it quickly, then estimate the "diameter" of your object (even if it's square), and multiply by the distance between their centers (minus 1 radius at each end for a total of 1 diameter). This'll be blazing fast and pretty close.
Update: misread the question, I thought you literally wanted "the area".
You can still approximate it as above, but determine the side points as the points on the imaginary circles, 90 degrees off the line that connects the two. Again, it's approximate, but it keeps you from having to calculate "closest side of the object" and "closest points to a line".
Update 2:
Actually, even better: sort the points of S1 in order of how far they are from the center of S2. Pick the 2nd and 3rd closest. Sort the points of S2 in order of how far they are from the center of S1. Pick the 2nd and 3rd closest. Those are the 4 vertices. The "1st" closest is the one directly pointing at the other object, so the 2nd and 3rd are the "side" ones, in terms of facing the other object.

Resources