Here is another implementation. It assumes that all the intervals lie in the specified range and intervals are sorted and aren't overlapping:
integerIntervalComplement[completeInterval : {start_, end_}, {subIntervals___}] :=
If[First[#2] - Last[#1] <= 1, Nothing, {Last[#1] + 1, First[#2] - 1}] & @@@
Partition[{{start - 1}, subIntervals, {end + 1}}, 2, 1];
Testing:
integerIntervalComplement[{1, 80}, {{3, 7}, {17, 43}, {64, 70}}]
{{1, 2}, {8, 16}, {44, 63}, {71, 80}}
integerIntervalComplement[{1, 80}, {{1, 7}, {64, 80}}]
{{8, 63}}
integerIntervalComplement[{1, 80}, {{2, 7}, {64, 79}}]
{{1, 1}, {8, 63}, {80, 80}}
integerIntervalComplement[{1, 80}, {}]
{{1, 80}}
If the intervals overlap, one can preprocess them first using Interval
, for example:
List @@ Interval @@ {{30, 40}, {3, 7}, {8, 12}, {1, 10}}
{{1, 12}, {30, 40}}
This also removes the condition for subintervals to be sorted.