Example #1
0
        static private ReadOnlyIntervalList Normalize(List <Interval> intervals, out bool isBottom)
        {
            Contract.Requires(intervals != null);

            Contract.Ensures(Contract.Result <ReadOnlyIntervalList>() != null);

            if (intervals.Count <= 1)
            {
                isBottom = false;
                return(AsReadOnly(intervals));
            }

            intervals.Sort((a, b) =>
                           a.Equals(b) ?
                           0 :
                           (a.UpperBound <= b.LowerBound ? -1 : 1));

            var result  = new List <Interval>(intervals.Count);
            var bottoms = 0;

            var prev = null as Interval;

            for (var i = 0; i < intervals.Count; i++)
            {
                var intv = intervals[i];

                // Skip repetitions
                if (prev == intv)
                {
                    continue;
                }

                if (intv.IsBottom)
                {
                    bottoms++;

                    continue;
                }

                if (intv.IsTop)
                {
                    isBottom = false;

                    return(EmptyReadOnlyList);
                }

                if (prev != null)
                {
                    var refined = true;
                    while (refined && result.Count > 0)
                    {
                        prev = result[result.Count - 1];

                        if (Interval.AreConsecutiveIntegers(prev, intv)) // The intervals are consecutive, so we join them together
                        {
                            result.RemoveAt(result.Count - 1);           // remove the last element
                            intv = prev.Join(intv);
                        }
                        else if (prev.LessEqual(intv))         // The last element we added is subsumed by the next one
                        {
                            result.RemoveAt(result.Count - 1); // remove the last element
                        }
                        else if (intv.LessEqual(prev))         // The last element we added subsumes the next one
                        {
                            goto nextIteration;
                        }
                        else if (prev.OverlapsWith(intv))      // If they are not included by they overlap, we take the join
                        {
                            result.RemoveAt(result.Count - 1); // remove the last element
                            intv = prev.Join(intv);
                        }
                        else
                        {
                            refined = false;      // Done, we cannot do better
                        }
                    }
                }
                prev = intv;
                result.Add(intv);

nextIteration:
                ;
            }

            isBottom = bottoms == intervals.Count;

            return(AsReadOnly(result));
        }