0

I have a 2D array (n * m) as a canvas and coordinates of Used points (startingPoints) in it. I have to calculate, how many points in it is not fieldable with floodfill from outside of the canvas. Field can go only in 4 directions and there are three types of points: Free, Fielded, Used. Used point is not fieldable and field not go over it. So count of unfieldable points is n*m-fieldable-startingPoints.

Now I do it like this: I run floodfill with stack from every point of border and I calculate, how many points are fielded.

But this is not usable for canvas, with dimensions 10^18*10^18. This wants a lot of memory and I must find better solution than using this classic floodfill.

Can someone help with better solution?

  • could you explain a bit more what does field mean? Is it an area within canvas enclosed by used/starting points? Is the field defined by the used points always closed shape, or are is the question trying to find the answer to closed filed or open field? – diginoise Feb 26 '18 at 18:07
  • @diginoise I edited question. For first example is result 1 (green pnt). For second is 0 (none unfieldable point) –  Feb 26 '18 at 19:18

2 Answers2

1

You could flip the problem on its head and search for points which appear inside of a field by using Point In Polygon technique.

Once you identified such point, you run a flood-fill starting from it. If flood fill ever touches the boundary, then your point and all points filled by this run of flood fill are discarded from the candidates since these are fieldable.

You repeat this procedure by finding points inside fields, which have not yet been filled.

Durring each flood fill you keep the count of filled points, and if given flood fill finishes and none of its leaves are on the boundary you include the count of that fill in the overall count of un-fieldable points.

diginoise
  • 7,352
  • 2
  • 31
  • 39
  • Wouldn't that require pre-existing knowledge of the "polygons" (aka the closed groups of un-fieldable cells)? If he knew that then the solution is much much easier and wouldn't even need PiP. – xtratic Feb 27 '18 at 13:50
  • the whole approach is a fishing expedition. You scan the shapes created by **used points** and assume them to be polygons. Then run flood fill from a point you deem INSIDE and if any points resulting from that fill touch the border, then you can mark all of these points as fieldable. Then rinse and repeat. – diginoise Feb 27 '18 at 13:59
  • The "scan the shapes created by used points" is not exactly a trivial problem and would take a lot of processing on its own. – xtratic Feb 27 '18 at 18:34
  • @xtratic scanning would involve visiting all MxN points in the worst case scenario. Running flood fill will cost O(m * n) but as you start filling the canvas, scanning will be skipping the already filled points, just as in your answer. In OP's and your method you still have to scan the whole canvas to perform the final count. OP's and your method are filling from the outside in, I fill from the inside out... Both have merit and one will outperform the other depending on the actual size and shape created by used points. – diginoise Feb 28 '18 at 09:21
  • @diginiose Sure those steps wouldn't be so bad, but I still think "scanning the shapes" (creating the polygons) is non-trivial and would be the main issue. How would you personally go about doing it? (update answer since it wouldn't fit in comments) – xtratic Feb 28 '18 at 15:12
  • @xtratic this is becoming a long thread - I will try to clarify in the answer. By **scanning** I mean running the PiP algo as a scanning line across the canvas. It's relatively simple algorithm and does not involve that much (I think) – diginoise Feb 28 '18 at 15:25
  • I'm really not understanding your idea still. How do you identify points which appear inside of a field by using PiP when you're just running the PiP algo as a scanning line across the canvas? Your answer is much too vague for me. – xtratic Feb 28 '18 at 15:52
0

I'm not 100% sure I understand what you want.

I'm imagining something like a labyrinth with multiple possible starting points on the outside edge, and you want to know all the possible areas that can be visited/filled from the outside?

The solution to make it more efficient is to cache values so that you don't go recalculating fills that were already calculated.

Make an other 2d array of equal size to keep track of already filled points.

Something like byte[][] filledPoints = new byte[n][m]; initialized with 0 meaning unfilled.

Just for example:

final byte UNFILLED = 0;
final byte RED = 1;
final byte BLUE = 2;

When you do a fill, for each point you visit mark that point with a "fill-color" to say that it was already calculated.

Eg. filledPoints[0][1] = RED

BUT, when doing a fill, if the point you are starting on is already filled, then that whole fill that you are about to do has already been calculated by a previous fill.

if(filledPoints[x][y] != UNFILLED){
    // Then this fill was already filled with the color of filledPoint[x][y]
}

So if it was already calculated then you don't need to calculate it again, so move on to the next starting point that you want to try to fill and check if that is already filled.

When you find a fill area that is not already filled, then start filling it with a new "color", and keep track of the area that gets filled.

Eg. filledPoints[0][386] = BLUE

The un-flood-fillable area is of course the total area minus the sum of all flood filled areas.

xtratic
  • 4,600
  • 2
  • 14
  • 32
  • Yes, this works, but if is labyrinth with dimensions 10^18 * 10^18 it is not possible make this. It is not possible to have in memory any whole line. I added image into question for better explanation. I have to count green points in image. –  Feb 26 '18 at 19:22
  • @Ferko I have an idea but I don't have the time to post it now. Stay tuned. – xtratic Feb 26 '18 at 21:12
  • @Ferko Just to clarify, is your goal to simply count the number of non fillable cells? Or is it to find the locations of all unfillable cells? – xtratic Feb 26 '18 at 21:18
  • @Ferko Sorry, I'll have to get to this tomorrow. The solution is a bit complicated to type up. I want to get a good code example for you. – xtratic Feb 27 '18 at 00:46
  • Goal is to count non fielable cells. Thanks, I will wait. –  Feb 27 '18 at 09:00
  • @Ferko You can read each cell in the grid as a stream right? Eg. `Scanner gridStream = new Scanner(new FileInputStream("gridFile"));` `byte cellData = gridStream.nextByte();` To test my method, could I possibly have that grid file, and the format so I can read it? – xtratic Feb 27 '18 at 16:05
  • @Ferko What I need to be able to do is read a stream of the grid cells only keeping a single cell in memory at a time. So I need to be able to read the grid cells left-to-right and top-to-bottom, or something like that, it doesn't really matter the direction. – xtratic Feb 27 '18 at 18:28
  • format of input is like this: on first line are m n k - dimensions of grid and number of used points. On next k lines are xi yi - coordinates of i-th point. In input isnt whole grid –  Feb 28 '18 at 09:00
  • @Ferko Ahh, so the file only has the `Used` points in it? That will change my processing a little bit. Is there a strict order to the points? (pelase say yes). And could you maybe share this data file on Pastebin or something, so I can test when I finish my algorithm. I've only been able to work on it on and off over the past few days, sorry it's taking a while, I hope this isn't urgent. – xtratic Feb 28 '18 at 14:36
  • Yes, only used points. Points aren't sorted. This is example of first picture: https://pastebin.com/f4m6fYfD `3 3 4\n 2 1\n 0 1\n 1 0\n 1 2\n` You are great if you want to help me. It is not very urgent. –  Feb 28 '18 at 17:35
  • @Freko Not sorted makes this significantly harder. And just sorting such a potentially large list is difficult on it's own (possibly 10^36 points if all points are used). This may take a while. Would using a local database be ok (MySQL maybe)? That would make handling the memory aspect much much easier. In general we're probably gonna have to use storage to avoid running out of memory. – xtratic Mar 01 '18 at 02:14
  • @Freko Oh, that makes many parts of the problem a whole lot simpler then. – xtratic Mar 01 '18 at 13:23