Let\'s say you have a set of ranges:
Obviously, these range
Pseudocode:
unusedRanges = [ (each of your ranges) ]
rangesInUse = []
usedRanges = []
beginningBoundary = nil
boundaries = [ list of all your ranges' start and end values, sorted ]
resultRanges = []
for (boundary in boundaries) {
rangesStarting = []
rangesEnding = []
// determine which ranges begin at this boundary
for (range in unusedRanges) {
if (range.begin == boundary) {
rangesStarting.add(range)
}
}
// if there are any new ones, start a new range
if (rangesStarting isn't empty) {
if (beginningBoundary isn't nil) {
// add the range we just passed
resultRanges.add(beginningBoundary, boundary - 1, [collected values from rangesInUse])
}
// note that we are starting a new range
beginningBoundary = boundary
for (range in rangesStarting) {
rangesInUse.add(range)
unusedRanges.remove(range)
}
}
// determine which ranges end at this boundary
for (range in rangesInUse) {
if (range.end == boundary) {
rangesEnding.add(range)
}
}
// if any boundaries are ending, stop the range
if (rangesEnding isn't empty) {
// add the range up to this boundary
resultRanges.add(beginningBoundary, boundary, [collected values from rangesInUse]
for (range in rangesEnding) {
usedRanges.add(range)
rangesInUse.remove(range)
}
if (rangesInUse isn't empty) {
// some ranges didn't end; note that we are starting a new range
beginningBoundary = boundary + 1
}
else {
beginningBoundary = nil
}
}
}
Unit test:
At the end, resultRanges should have the results you're looking for, unusedRanges and rangesInUse should be empty, beginningBoundary should be nil, and usedRanges should contain what unusedRanges used to contain (but sorted by range.end).