This algorithm counts how many boxes are islands.
will create an imaginary line for each box (minX, maxY)-(minX, infinity) and count the number of intersections from this line with the others boxes. If the number of intersections is even then box is land otherwise it is sea.
+ + +
| | |
| | |
minX, |axY | |
| | |
v------X-------+ |
| | | |
| | | |
| | | |
| | | |
+------X-------+ |
v |
minX, maxX | +
+------------X------------+
| minX,|maxY |
| v |
| +-------+ |
| | | |
| | | |
| +-------+ |
| |
| |
+-------------------------+
I will apply an optimization and sort the list of boxes by maxY. Boxes with bigger maxY will have smaller indexes.
+ + +
| | |
| | |
minX, |axY | |
| | |
v------X-------+ |
| | | |
| 0 | | |
| | | |
| | | |
+------X-------+ |
v | +----------+
minX, maxX | + | 1 |
+------------X------------+ | |
| 2 minX,|maxY | | |
| v | +----------+
| +-------+ |
| | 3 | |
| | | | +-------------+
| +-------+ | | 4 |
| | | |
| | | |
+-------------------------+ | |
+-------------+
+-------------+
| 5 |
+-------------+
Using this optimization, each box will check intersection only with the boxes that have smaller indexes.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
struct Box {
double minX;
double minY;
double maxX;
double maxY;
};
int CountSorted(std::vector<Box>& boxes)
{
//pre-condition - boxes sorted by maxY
int landCount = 0;
for (int i = 0; i < (int)boxes.size(); i++)
{
int intersectionCount = 0;
const double x = boxes[i].minX;
const double y = boxes[i].maxY;
for (int k = i - 1; k >= 0; k--)
{
assert(boxes[k].maxY >= y);
if (x >= boxes[k].minX && x <= boxes[k].maxX)
{
//check the intersection with maxY
if (boxes[k].maxY > y)
{
intersectionCount++;
}
//check the intersection with minY
if (boxes[k].minY > y)
{
intersectionCount++;
}
}
}
if (intersectionCount % 2 == 0)
{
//if even then box is land
landCount++;
}
}
return landCount;
}
int CountUnsorted(std::vector<Box>& boxes)
{
//boxes will be sorted by maxY
std::sort(boxes.begin(), boxes.end(), [](const Box& a, const Box& b)
{
return a.maxY > b.maxY;
});
return CountSorted(boxes);
}
void Test()
{
std::vector<Box> boxes0;
assert(CountUnsorted(boxes0) == 0);
std::vector<Box> boxes1 = {
{ 1.0, 1.0, 3.0, 3.0 }
};
assert(CountUnsorted(boxes1) == 1);
std::vector<Box> boxes2 = {
{ 1.0, 1.0, 3.0, 3.0 },
{ 1.0, 4.0, 1.0, 5.0 }
};
assert(CountUnsorted(boxes2) == 2);
std::vector<Box> boxes3 = {
{ 5.0, 5.0, 6.0, 6.0 },
{ 4.0, 4.0, 7.0, 7.0 }
};
assert(CountUnsorted(boxes3) == 1);
std::vector<Box> boxes4 =
{
{ 1.0, 1.0, 10.0, 6.0 },
{ 1.5, 1.5, 6.0, 5.0 },
{ 2.0, 2.0, 3.0, 3.0 },
{ 2.0, 3.5, 3.0, 4.5 },
{ 3.5, 2.0, 5.5, 4.5 },
{ 4.0, 3.5, 5.0, 4.0 },
{ 4.0, 2.5, 5.0, 3.0 },
{ 7.0, 3.0, 9.5, 5.5 },
{ 7.5, 4.0, 8.0, 5.0 },
{ 8.5, 3.5, 9.0, 4.5 },
{ 3.0, 7.0, 8.0, 10.0 },
{ 5.0, 7.5, 7.5, 9.5 },
{ 5.5, 8.0, 6.0, 9.0 },
{ 6.5, 8.0, 7.0, 9.0 }
};
assert(CountUnsorted(boxes4) == 9);
}
I make the ascii draw using: http://stable.ascii-flow.appspot.com/#Draw