/// <summary> /// Returns a collection of elements at what would be the i'th element for i \in [startIdx,lastIdx]. startIdx and lastIdx are 0-based. /// </summary> private RangeCollection ElementsAt(long startIndex, long lastIndex) { if (lastIndex < startIndex || startIndex < 0 || lastIndex >= Count()) { throw new ArgumentOutOfRangeException(string.Format("{0}-{1} must be a non-empty range that falls between 0 and {2}", startIndex, lastIndex, Count() - 1)); } RangeCollection result = new RangeCollection(); long countSoFar = 0; foreach (KeyValuePair <long, long> range in Ranges) { long rangeLength = range.Value - range.Key + 1; if (startIndex - countSoFar < rangeLength) { long start = range.Key + startIndex - countSoFar; long lastIfContinuousRange = range.Key + lastIndex - countSoFar; long last = Math.Min(range.Value, lastIfContinuousRange); // if startIdx-lastIdx falls completely in range, then take 2nd entry. result.AddRange(start, last); if (lastIfContinuousRange <= range.Value) // if this range covers the remaining indeces, we're done. { return(result); } else { startIndex = countSoFar + rangeLength; } } countSoFar += rangeLength; } throw new NotImplementedException("If we get here, then there's a bug in the implementation."); }
/// <summary> /// Returns the competeCollection - thisCollection /// </summary> /// <returns></returns> public RangeCollection Complement(long fullRangeBegin, long fullRangeEnd) { RangeCollection result = new RangeCollection(); long rangeLeftToCoverBegin = fullRangeBegin; foreach (KeyValuePair <long, long> range in Ranges) { long start = range.Key; long last = range.Value; if (start > rangeLeftToCoverBegin) { result.AddRange(rangeLeftToCoverBegin, Math.Min(start - 1, fullRangeEnd)); } rangeLeftToCoverBegin = Math.Max(rangeLeftToCoverBegin, last + 1); if (rangeLeftToCoverBegin > fullRangeEnd) { break; } } if (rangeLeftToCoverBegin <= fullRangeEnd) { result.AddRange(rangeLeftToCoverBegin, fullRangeEnd); } return(result); }
/// <summary> /// Parses strings of the form -10--5,-2-10,12-12 . Spaces are allowed, no other characters are. /// If mergeOverlappingRanges, then, for example, 2-3,4-5 is represented /// as 2-5. Otherwise, they're maintained as separate ranges. The only difference is in the behavior of the ToString() call. /// By extension, this will change how a RangeCollection is parsed into a RangeCollectionCollection using the latter's /// GetInstance(RangeCollection) initializer. /// </summary> /// <param name="ranges">A range or the string empty. \"empty\" will return an empty range.</param> /// <returns>a new RangeCollection</returns> public static RangeCollection Parse(string ranges) { ranges = ranges.Trim(); RangeCollection aRangeCollection = new RangeCollection(); aRangeCollection.InternalParse(ranges); return(aRangeCollection); }
/// <summary> /// Returns a collection of elements at what would be the i'th element for i \in rangeCollectionOfIndeces. /// </summary> /// <param name="rangeCollectionOfIndeces">0-based indeces.</param> public RangeCollection ElementsAt(RangeCollection rangeCollectionOfIndeces) { RangeCollection result = new RangeCollection(); foreach (KeyValuePair <long, long> range in rangeCollectionOfIndeces.Ranges) { result.AddRangeCollection(ElementsAt(range.Key, range.Value)); } return(result); }
/// <summary> /// Add the integers of one RangeCollection to this RangeCollection. /// </summary> /// <param name="rangeCollection">The RangeCollection to add</param> /// <returns>true of all the elements added are new; otherwise, false</returns> public bool TryAddRangeCollection(RangeCollection rangeCollection) { bool allNew = true; foreach (KeyValuePair <long, long> startAndLast in rangeCollection.Ranges) { allNew &= TryAdd(startAndLast.Key, startAndLast.Value - startAndLast.Key + 1); } return(allNew); }
/// <summary> /// Tells if this RangeCollection is a superset of another. An an equal RangeCollection is a superset. /// </summary> /// <param name="rangeCollection">The RangeCollection that may be the subset</param> /// <returns>true, if this RangeCollection is a superset; otherwise, false</returns> public bool Contains(RangeCollection rangeCollection) { foreach (KeyValuePair <long, long> range in this.Ranges) { if (!Contains(range.Key, range.Value)) { return(false); } } return(true); }
static public void Test() { RangeCollection aRangeCollection = new RangeCollection(); aRangeCollection.Add(0); Helper.CheckCondition("0" == aRangeCollection.ToString()); aRangeCollection.Add(1); Helper.CheckCondition("0-1" == aRangeCollection.ToString()); aRangeCollection.Add(4); Helper.CheckCondition("0-1,4" == aRangeCollection.ToString()); aRangeCollection.Add(5); Helper.CheckCondition("0-1,4-5" == aRangeCollection.ToString()); aRangeCollection.Add(7); Helper.CheckCondition("0-1,4-5,7" == aRangeCollection.ToString()); aRangeCollection.Add(2); Helper.CheckCondition("0-2,4-5,7" == aRangeCollection.ToString()); aRangeCollection.Add(3); Helper.CheckCondition("0-5,7" == aRangeCollection.ToString()); aRangeCollection.Add(6); Helper.CheckCondition("0-7" == aRangeCollection.ToString()); aRangeCollection.Add(-10); Helper.CheckCondition("-10,0-7" == aRangeCollection.ToString()); aRangeCollection.Add(-5); Helper.CheckCondition("-10,-5,0-7" == aRangeCollection.ToString()); string range = "-10--5,-3,-2-1,1-5,7-12,13-15,14-16,20-25,22-23"; aRangeCollection = RangeCollection.Parse(range); Console.WriteLine(range); Console.WriteLine(aRangeCollection); range = "1-5,0,4-10,-10--5,-12--3,15-20,12-21,-13"; aRangeCollection = RangeCollection.Parse(range); Console.WriteLine(range); Console.WriteLine(aRangeCollection); Console.WriteLine("Count: " + aRangeCollection.Count()); Console.WriteLine("Count -5 to 2: " + aRangeCollection.Count(-5, 2)); //RangeCollectionCollection rcc = RangeCollectionCollection.GetInstance(aRangeCollection); //Console.WriteLine(rcc); //Console.WriteLine(rcc.GetContainingRangeCollection(-12)); //Console.WriteLine(rcc.GetContainingRangeCollection(-10)); //Console.WriteLine(rcc.GetContainingRangeCollection(-5)); //Console.WriteLine(rcc.GetContainingRangeCollection(3)); //Console.WriteLine(rcc.GetContainingRangeCollection(15)); }
/// <summary> /// Tests equality between two range collections /// </summary> /// <param name="rangeCollection">The range collection we're testing against</param> /// <returns>True if and only if the ranges are identical</returns> public bool Equals(RangeCollection rangeCollection) { if (null == rangeCollection) { return(false); } if (!_startItems.SequenceEqual(rangeCollection._startItems)) { return(false); } if (!_itemToLength.Keys.SequenceEqual(rangeCollection._itemToLength.Keys)) { return(false); } if (!_itemToLength.Values.SequenceEqual(rangeCollection._itemToLength.Values)) { return(false); } return(true); }
/// <summary> /// Create a RangeCollection by doing a deep copy of a RangeCollection /// </summary> /// <param name="rangeCollection">A new RangeCollection</param> public RangeCollection(RangeCollection rangeCollection) : this() { _startItems = new List <long>(rangeCollection._startItems); _itemToLength = new SortedDictionary <long, long>(rangeCollection._itemToLength); }
/// <summary> /// Add the integers of one RangeCollection to this RangeCollection. /// </summary> /// <param name="rangeCollection">The RangeCollection to add</param> public void AddRangeCollection(RangeCollection rangeCollection) { TryAddRangeCollection(rangeCollection); }