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

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.

Related

what algorithm or approach for placing rectangles without overlapp

I have a big rectangle of size 12*12. Now I have 6 rectangles already placed on the floor of that rectangle. I know the center coordinate of that pre-placed module. Now I have few another 14 rectangles to place upon that floor of that rectangle. How to do so?
here all my pre placed block those having center coordinate as say (2,5),(5,7),(9,2),(7,8),(11,9),(3,11).
Now how could I place 14 another rectangle in this floor so that it would not over lap with any preplaced block.
I would like to code in MATLAB..but what approach should I follow?
If a nice even placement is important, I suggest you look up simulated force-based graph layout. In this problem, you'll use simulated forces pushing the rectangles apart and also away from the border rectangle according to Coulomb's law. The initial configuration is randomly selected. You'll want to give the rectangles mass proportional to their area, I think. You don't have any spring forces due to edges, which makes it easier. The iteration to solve the differential equations of motion will be easy in Matlab. Or there may well be a toolkit to do it for you. Animations of these algorithms are fun.
Unfortunately with constrained problems like this, the fixed rectangles can form barriers that prevent the moving rectangles from getting to a non-overlapping solution. (Think of the case where the fixed rectangles are in a line down the middle and all the moving ones get "trapped" on one side or the other. The same thing happens in graph layout if some nodes have fixed locations.) There are various strategies for overcoming these bad cases. One is to start with no fixed objects at all, let the moving rectangles come to an equilibrium, then add the fixed ones one at a time, largest first, allowing the system regain equilibrium each time. Another, simpler one is just to start from different random initial conditions until you find one that works. There are also approaches related to simulated annealing, which is too big a topic to discuss here.
Here is a function to check overlap for two rectangles. you could loop it to check for more number of rectangles based on #Dov's idea.
For two rectangles Ri, i = 1,2, with centers (xi,yi) and half-lengths of their sides ai,bi > 0 (assuming that the sides are aligned with the coordinate axes).
Here is my implementation based on above equation:
In my code i've taken xcPosition and ycPosition as the center position of the rectangle.
Also length and breadth are the magnitude of sides of the rectangle.
function [ overLap, pivalue ] = checkOverlap( xcPosition1,ycPosition1,xcPosition2,ycPosition2,length1,breadth1,length2,breadth2 )
pix = max((xcPosition2 - xcPosition1 -(length1/2)-(length2/2)),(xcPosition1 -xcPosition2 -(length2/2)-(length1/2)));
piy = max((ycPosition2 - ycPosition1 -(breadth1/2)-(breadth2/2)),(ycPosition1 -ycPosition2 -(breadth2/2)-(breadth1/2)));
pivalue = max(pix, piy);
if (pivalue < 0)
overLap = 1; %// Overlap exists
else
overLap = 0; %// No overlap
end
end
You could also use the pivalue to know the degree of overlap or Non-overlap
The Pseudo-code for looping would be something like this:
for i = 1 : 14
for j = 1 : i-1 + 6 already placed parts
%// check for overlap using the above function here
%// place the part if there is no overlap
end
end
With such a small number, put each rectangle in a list. Each time you add a new rectangle, make sure the new one does not overlap with any of the existing ones.
This is O(n^2), so if you plan to increase to 10^3 or more rectangles you will need a better algorithm, but otherwise you're fine.
Now if your problem specifies that you might not be able to fit them all, then you will have to backtrack and keep trying different places. That is an N! problem, but if you have a lot of open space, many solutions will be possible.

Nearest neighbor search in 2D using a grid partitioning

I have a fairly large set of 2D points (~20000) in a set, and for each point in the x-y plane want to determine which point from the set is closest. (Actually, the points are of different types, and I just want to know which type is closest. And the x-y plane is a bitmap, say 640x480.)
From this answer to the question "All k nearest neighbors in 2D, C++" I got the idea to make a grid. I created n*m C++ vectors and put the points in the vector, depending on which bin it falls into. The idea is that you only have to check the distance of the points in the bin, instead of all points. If there is no point in the bin, you continue with the adjacent bins in a spiralling manner.
Unfortunately, I only read Oli Charlesworth's comment afterwards:
Not just adjacent, unfortunately (consider that points in the cell two
to the east may be closer than points in the cell directly north-east,
for instance; this problem gets much worse in higher dimensions).
Also, what if the neighbouring cells happen to have less than 10
points in them? In practice, you will need to "spiral out".
Fortunately, I already had the spiraling code figured out (a nice C++ version here, and there are other versions in the same question). But I'm still left with the problem:
If I find a hit in a cell, there could be a closer hit in an adjacent cell (yellow is my probe, red is the wrong choice, green the actual closest point):
If I find a hit in an adjacent cell, there could be a hit in a cell 2 steps away, as Oli Charlesworth remarked:
But even worse, if I find a hit in a cell two steps away, there could still be a closer hit in a hit three steps away! That means I'd have to consider all cells with dx,dy= -3...3, or 49 cells!
Now, in practice this won't happen often, because I can choose my bin size so the cells are filled enough. Still, I'd like to have a correct result, without iterating over all points.
So how do I find out when to stop "spiralling" or searching? I heard there is an approach with multiple overlapping grids, but I didn't quite understand it. Is it possible to salvage this grid technique?
Since the dimensions of your bitmap are not large and you want to calculate the closest point for every (x,y), you can use dynamic programming.
Let V[i][j] be the distance from (i,j) to the closest point in the set, but considering only the points in the set that are in the "rectangle" [(1, 1), (i, j)].
Then V[i][j] = 0 if there is a point in (i, j), or V[i][j] = min(V[i'][j'] + dist((i, j), (i', j'))) where (i', j') is one of the three neighbours of (i,j):
i.e.
(i - 1, j)
(i, j - 1)
(i - 1, j - 1)
This gives you the minimum distance, but only for the "upper left" rectangle. We do the same for the "upper right", "lower left", and "lower right" orientations, and then take the minimum.
The complexity is O(size of the plane), which is optimal.
For you task usually a Point Quadtree is used, especially when the points are not evenly distributed.
To save main memory you als can use a PM or PMR-Quadtree which uses buckets.
You search in your cell and in worst case all quad cells surounding the cell.
You can also use a k-d tree.
A solution im trying
First make a grid such that you have an average of say 1 (more if you want larger scan) points per box.
Select the center box. Continue selecting neighbor boxes in a circular manner until you find at least one neighbor. At this point you can have 1 or 9 or so on boxes selected
Select one more layer of adjacent boxes
Now you have a fairly small list of points, usually not more than 10 which you can punch into the distance formula to find the nearest neighbor.
Since you have on average 1 points per box, you will mostly be selecting 9 boxes and comparing 9 distances. Can adjust grid size according to your dataset properties to achieve better results.
Also, if your data has a lot of variance, you can try 2 levels of grid (or even more) so if selection works and returns more than 50 points in a single query, start a next grid search with a grid 1/10th the size ...
One solution would be to construct multiple partitionings with different grid sizes.
Assume you create partitions at levels 1,2,4,8,..
Now, search for a point in grid size 1 (you are basically searching in 9 squares). If there is a point in the search area and if distance to that point is less than 1, stop. Otherwise move on to the next grid size.
The number of grids you need to construct is about twice as compared to creating just one level of partitioning.

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.

Randomly and efficiently filling space with shapes

What is the most efficient way to randomly fill a space with as many non-overlapping shapes? In my specific case, I'm filling a circle with circles. I'm randomly placing circles until either a certain percentage of the outer circle is filled OR a certain number of placements have failed (i.e. were placed in a position that overlapped an existing circle). This is pretty slow, and often leaves empty spaces unless I allow a huge number of failures.
So, is there some other type of filling algorithm I can use to quickly fill as much space as possible, but still look random?
Issue you are running into
You are running into the Coupon collector's problem because you are using a technique of Rejection sampling.
You are also making strong assumptions about what a "random filling" is. Your algorithm will leave large gaps between circles; is this what you mean by "random"? Nevertheless it is a perfectly valid definition, and I approve of it.
Solution
To adapt your current "random filling" to avoid the rejection sampling coupon-collector's issue, merely divide the space you are filling into a grid. For example if your circles are of radius 1, divide the larger circle into a grid of 1/sqrt(2)-width blocks. When it becomes "impossible" to fill a gridbox, ignore that gridbox when you pick new points. Problem solved!
Possible dangers
You have to be careful how you code this however! Possible dangers:
If you do something like if (random point in invalid grid){ generateAnotherPoint() } then you ignore the benefit / core idea of this optimization.
If you do something like pickARandomValidGridbox() then you will slightly reduce the probability of making circles near the edge of the larger circle (though this may be fine if you're doing this for a graphics art project and not for a scientific or mathematical project); however if you make the grid size 1/sqrt(2) times the radius of the circle, you will not run into this problem because it will be impossible to draw blocks at the edge of the large circle, and thus you can ignore all gridboxes at the edge.
Implementation
Thus the generalization of your method to avoid the coupon-collector's problem is as follows:
Inputs: large circle coordinates/radius(R), small circle radius(r)
Output: set of coordinates of all the small circles
Algorithm:
divide your LargeCircle into a grid of r/sqrt(2)
ValidBoxes = {set of all gridboxes that lie entirely within LargeCircle}
SmallCircles = {empty set}
until ValidBoxes is empty:
pick a random gridbox Box from ValidBoxes
pick a random point inside Box to be center of small circle C
check neighboring gridboxes for other circles which may overlap*
if there is no overlap:
add C to SmallCircles
remove the box from ValidBoxes # possible because grid is small
else if there is an overlap:
increase the Box.failcount
if Box.failcount > MAX_PERGRIDBOX_FAIL_COUNT:
remove the box from ValidBoxes
return SmallCircles
(*) This step is also an important optimization, which I can only assume you do not already have. Without it, your doesThisCircleOverlapAnother(...) function is incredibly inefficient at O(N) per query, which will make filling in circles nearly impossible for large ratios R>>r.
This is the exact generalization of your algorithm to avoid the slowness, while still retaining the elegant randomness of it.
Generalization to larger irregular features
edit: Since you've commented that this is for a game and you are interested in irregular shapes, you can generalize this as follows. For any small irregular shape, enclose it in a circle that represent how far you want it to be from things. Your grid can be the size of the smallest terrain feature. Larger features can encompass 1x2 or 2x2 or 3x2 or 3x3 etc. contiguous blocks. Note that many games with features that span large distances (mountains) and small distances (torches) often require grids which are recursively split (i.e. some blocks are split into further 2x2 or 2x2x2 subblocks), generating a tree structure. This structure with extensive bookkeeping will allow you to randomly place the contiguous blocks, however it requires a lot of coding. What you can do however is use the circle-grid algorithm to place the larger features first (when there's lot of space to work with on the map and you can just check adjacent gridboxes for a collection without running into the coupon-collector's problem), then place the smaller features. If you can place your features in this order, this requires almost no extra coding besides checking neighboring gridboxes for collisions when you place a 1x2/3x3/etc. group.
One way to do this that produces interesting looking results is
create an empty NxM grid
create an empty has-open-neighbors set
for i = 1 to NumberOfRegions
pick a random point in the grid
assign that grid point a (terrain) type
add the point to the has-open-neighbors set
while has-open-neighbors is not empty
foreach point in has-open-neighbors
get neighbor-points as the immediate neighbors of point
that don't have an assigned terrain type in the grid
if none
remove point from has-open-neighbors
else
pick a random neighbor-point from neighbor-points
assign its grid location the same (terrain) type as point
add neighbor-point to the has-open-neighbors set
When done, has-open-neighbors will be empty and the grid will have been populated with at most NumberOfRegions regions (some regions with the same terrain type may be adjacent and so will combine to form a single region).
Sample output using this algorithm with 30 points, 14 terrain types, and a 200x200 pixel world:
Edit: tried to clarify the algorithm.
How about using a 2-step process:
Choose a bunch of n points randomly -- these will become the centres of the circles.
Determine the radii of these circles so that they do not overlap.
For step 2, for each circle centre you need to know the distance to its nearest neighbour. (This can be computed for all points in O(n^2) time using brute force, although it may be that faster algorithms exist for points in the plane.) Then simply divide that distance by 2 to get a safe radius. (You can also shrink it further, either by a fixed amount or by an amount proportional to the radius, to ensure that no circles will be touching.)
To see that this works, consider any point p and its nearest neighbour q, which is some distance d from p. If p is also q's nearest neighbour, then both points will get circles with radius d/2, which will therefore be touching; OTOH, if q has a different nearest neighbour, it must be at distance d' < d, so the circle centred at q will be even smaller. So either way, the 2 circles will not overlap.
My idea would be to start out with a compact grid layout. Then take each circle and perturb it in some random direction. The distance in which you perturb it can also be chosen at random (just make sure that the distance doesn't make it overlap another circle).
This is just an idea and I'm sure there are a number of ways you could modify it and improve upon it.

Random Tile layout

I need to place tiles on a large grid radiating from a central point in a way that looks organic and random. New tiles will need to find an open space on the grid that is touching at least 1 other tile.
Can anyone point me in the right to direction to anything that might help with this?
Or some basic concepts I can read up on that are in this vein?
For example, in this picture, there is a shape already created (yellow) and I may be receiving a new tile, that may be 1x1, 2x2, or 3x3. Trying to find a good way to figure out where I can place the new tile so that it will be touching the maximum amount of current tiles.
Picture:
alt text http://osomer.com/grid.JPG
Alternatively, you could approach this problem as the yellow tiles "eroding" away at the blue/background. To do this, at every step, have a yellow tile add a fixed number to the "erosion sum" E of all of the background tiles neighboring it in a cardinal direction (and perhaps maybe a fraction of that to the background tiles neighboring it diagonally).
Then, when it comes time to place a new tile, you can, for each background tile, pick a random number from 0 to E; the greatest one is "eroded" away. Alternatively, you could do a simple weighted random choice, with E being their weights.
For 2x2 or 3x3 tiles, you can pick only from tiles that suitably "fit" a 2x2 or 3x3 square in it (that is, a 2x2 or 3x3 the eroded tile on its edge, so that it doesn't cause overlap with already-placed tiles). But really, you're never going to get something looking as natural as one-by-one erosion/tile placement.
You can save time recalculating erosion sums by having them persist with each iteration, only, when you add a new tile, up the erosion sums of the ones around it (a simple +=). At this point, it is essentially the same as another answer suggested, albeit with a different perspective/philosophy.
A sample grid of Erosion Sums E, with direct cardinal neighbors being +4, and diagonal neighbors being +1:
Erosion Sums http://img199.imageshack.us/img199/4766/erosion.png
The ones with a higher E are most likely to be "eroded" away; for example, in this one, the two little inlets on the west and south faces are most likely to be eroded away by the yellow, followed by the smaller bays on the north and east faces. Least likely are the ones barely touching the yellow by one corner. You can decide which one either by assigning a random number from 0 to E for each tile and eroding the one with the highest random number, or doing a simple weighted random selection, or by any decision method of your choice.
For purely random, you start with an empty grid and a "candidate" list (also empty).
Place the first tile in the centre of the grid, then add each adjacent tile to the one you just placed into the "candidate" list. Then, each turn, choose a random entry in the "candidate" list and place a tile there. Look at each adjancent grid location next to where you just placed the tile, and for each one that is also empty, put it on the "candidate" list for the next time around (if not already there).
To avoid creating holes in your tile grid, increase the probability of selecting a grid location based on the number of adjacent tiles that are already filled (so if only one adjacent tile is already filled, it has low probably. If they're all filled, it'll have a very high probability).
In pseudo code:
grid = new array[width,height];
candidates = new list();
function place_tile(x,y) {
// place the tile at the given location
grid[x,y] = 1;
// loop through all the adjacent grid locations around the one
// we just placed
for(y1 = y - 1; y1 < y + 1; y1++) {
for(x1 = x - 1; x1 < x + 1; x1++) {
// if this location doesn't have a tile and isn't already in
// the candidate list, add it
if (grid[x,y] != 1 && !candidates.contains(x1,y1)) {
candidates.add(x1,y1);
}
}
}
}
// place the first tile in the centre
place_tile(width/2, height/2);
while (!finished) {
// choose a random tile from the candidate list
int index = rand(0, candidates.length - 1);
// place a tile at that location (remove the entry from
// the candidate list)
x, y = candidates[index];
candidates.remove(index);
place_tile(x, y);
}
The problem with your question is that 'organic and random' can be many different things.
Let me show two links
generating random fractal terrain (look at section 'Cloudy Skies' and imagine that you turn it to b/w, or in your case yellow/background).
simulating erosion (look at the image under 'erode')
The two above samples are 'organic and random' to me, but you might not be satisfied with those. So, I think you will have to better define what is 'organic and random'.
For now, I'll take your definition of the guiding rule for adding new tiles (but don't think it is necessarily the same problem), which I read as:
Given two shapes (assuming bitmaps)
find the relative position of the
shapes such that the number of
touching sides is maximum
I will also assume
overlap is not allowed
you can leave holes inside the resulting, merged shape
you can not rotate shapes
Under such conditions you need to test less then xy solutions and in each you need to
- discard it if there is an overlap
- discard it if they do not touch
- if they touch then count the number of edges that are common
All three of the above tests can be done in constant time by scanning all the yellow tiles (number of which is konstx*y)
So, the above can be easily done in O(n^4), is that good enough for you?
Compute a random spanning tree for the dual graph, that is, the grid whose vertices are the centers of your cells. For that, start at the center of the grid and do a random depth-first search. Then plot cells fro increasing tree distance from the center.

Resources