patterncsharpMinor
Finding unconnected sets
Viewed 0 times
unconnectedsetsfinding
Problem
I have a list of boxes, and wish to group them into unconnected sets of overlapping boxes. (Note that two boxes A and B may not overlap each other, but if they are both overlapped by a box C, they will still be grouped together).
The following works ok, but I feel like it could be made a lot more concise with LINQ, or possibly made faster.
Edit: added the Box class. It's not all that interesting really.
```
private class Box
{
public Box(int xOrigin, int yOrigin, int size)
{
XOrigin = xOrigin;
YOrigin = yOrigin;
Size = size;
}
public int XOrigin;
public int YOrigin;
public int Size;
public override string ToString()
{
string s = "Box: "
+ "(" + XOrigin.ToString() + ", " + YOrigin.ToString() + ")"
+ " " + Size.ToString();
return s;
}
public bool Overlaps(Box b2)
{
if (XOrigin >= b2.XOrigin + b
The following works ok, but I feel like it could be made a lot more concise with LINQ, or possibly made faster.
private List> FindUnconnectedSets(List boxes)
{
List> unconnectedSets = new List>();
while (boxes.Count() != 0)
{
List set = new List();
bool found = true;
while (found)
{
found = false;
foreach (Box newBox in boxes)
{
if (set.Count != 0)
{
foreach (Box setBox in set)
{
if (newBox.Overlaps(setBox))
{
set.Add(newBox);
boxes.Remove(newBox);
found = true;
break;
}
}
}
else
{
set.Add(newBox);
boxes.Remove(newBox);
found = true;
}
if (found)
break;
}
}
unconnectedSets.Add(set);
}
return unconnectedSets;
}Edit: added the Box class. It's not all that interesting really.
```
private class Box
{
public Box(int xOrigin, int yOrigin, int size)
{
XOrigin = xOrigin;
YOrigin = yOrigin;
Size = size;
}
public int XOrigin;
public int YOrigin;
public int Size;
public override string ToString()
{
string s = "Box: "
+ "(" + XOrigin.ToString() + ", " + YOrigin.ToString() + ")"
+ " " + Size.ToString();
return s;
}
public bool Overlaps(Box b2)
{
if (XOrigin >= b2.XOrigin + b
Solution
Since we are talking about sets, it's probably better to use collection types that represent a set:
Another improvement you can make is to keep track of the boxes you've added to current set at the last iteration (horizon of your expansion), and try to match candidate boxes only with them.
Note that resulting solution doesn't use the knowledge about box matching logic, so it might be a good idea to extract the interface that defines the connection between elements (i.e. a method that checks for the presence of link between nodes).
As a result I've got the following solution:
And the
HashSet and ISet.Another improvement you can make is to keep track of the boxes you've added to current set at the last iteration (horizon of your expansion), and try to match candidate boxes only with them.
Note that resulting solution doesn't use the knowledge about box matching logic, so it might be a good idea to extract the interface that defines the connection between elements (i.e. a method that checks for the presence of link between nodes).
As a result I've got the following solution:
public interface IConnected
{
bool IsConnectedTo(T other);
}
public class Box: IConnected
{
....
public bool IsConnectedTo(Box other)
{
return Overlaps(other);
}
}And the
FindUnconnectedSets:public static List> FindUnconnectedSets(IEnumerable boxes) where T : IConnected
{
var remainingBoxes = new HashSet(boxes);
var unconnectedSets = new List>();
while (remainingBoxes.Count > 0)
{
var newBoxes = new[] { remainingBoxes.First() }; //on each iteration will contain newly added boxes to current set
var currentSet = new HashSet();
unconnectedSets.Add(currentSet);
do
{
currentSet.UnionWith(newBoxes);
remainingBoxes.ExceptWith(newBoxes);
newBoxes = remainingBoxes
.Where(remainingBox => newBoxes.Any(setBox => setBox.IsConnectedTo(remainingBox)))
.ToArray();
} while (newBoxes.Length > 0);
}
return unconnectedSets;
}Code Snippets
public interface IConnected<in T>
{
bool IsConnectedTo(T other);
}
public class Box: IConnected<Box>
{
....
public bool IsConnectedTo(Box other)
{
return Overlaps(other);
}
}public static List<ISet<T>> FindUnconnectedSets<T>(IEnumerable<T> boxes) where T : IConnected<T>
{
var remainingBoxes = new HashSet<T>(boxes);
var unconnectedSets = new List<ISet<T>>();
while (remainingBoxes.Count > 0)
{
var newBoxes = new[] { remainingBoxes.First() }; //on each iteration will contain newly added boxes to current set
var currentSet = new HashSet<T>();
unconnectedSets.Add(currentSet);
do
{
currentSet.UnionWith(newBoxes);
remainingBoxes.ExceptWith(newBoxes);
newBoxes = remainingBoxes
.Where(remainingBox => newBoxes.Any(setBox => setBox.IsConnectedTo(remainingBox)))
.ToArray();
} while (newBoxes.Length > 0);
}
return unconnectedSets;
}Context
StackExchange Code Review Q#23347, answer score: 2
Revisions (0)
No revisions yet.