/// <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 fullRangeLast) { 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, fullRangeLast)); } rangeLeftToCoverBegin = Math.Max(rangeLeftToCoverBegin, last + 1); if (rangeLeftToCoverBegin > fullRangeLast) { break; } } if (rangeLeftToCoverBegin <= fullRangeLast) { result.AddRange(rangeLeftToCoverBegin, fullRangeLast); } 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> /// Add the longs 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> /// Returns a collection of elements at what would be the nth element for i \in rangeCollectionOfIndeces. /// </summary> /// <param name="rangeCollectionOfIndeces">0-based indices.</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> /// 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 (!this.startItems.SequenceEqual(rangeCollection.startItems)) { return(false); } if (!this.itemToLength.Keys.SequenceEqual(rangeCollection.itemToLength.Keys)) { return(false); } if (!this.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() { this.startItems = new List <long>(rangeCollection.startItems); this.itemToLength = new SortedDictionary <long, long>(rangeCollection.itemToLength); }
/// <summary> /// Add the longs of one RangeCollection to this RangeCollection. /// </summary> /// <param name="rangeCollection">The RangeCollection to add</param> public void AddRangeCollection(RangeCollection rangeCollection) { TryAddRangeCollection(rangeCollection); }
private static IEnumerable <KeyValuePair <T, long> > UseSkipList <T>(IEnumerable <T> enumerable, RangeCollection skipListOrNull) { long rowIndex = -1; foreach (T t in enumerable) { ++rowIndex; if (null != skipListOrNull && skipListOrNull.Contains(rowIndex)) { continue; } yield return(new KeyValuePair <T, long>(t, rowIndex)); } }
/// <summary> /// This method will spread out the work items--like dealing cards around the table, you only get every other K'th card, /// where K is the number of people, when batchCount=1. (Or else you get sets of batchCount-contiguous cards). /// </summary> /// <typeparam name="T"></typeparam> /// <param name="enumerable"></param> /// <param name="pieceIndexRangeCollection"></param> /// <param name="pieceCount"></param> /// <param name="batchCount"></param> /// <param name="skipListOrNull"></param> /// <returns>The item and it's original index in the enumerable.</returns> public static IEnumerable <KeyValuePair <T, long> > DivideWork <T>(IEnumerable <T> enumerable, RangeCollection pieceIndexRangeCollection, long pieceCount, long batchCount, RangeCollection skipListOrNull) { if (pieceIndexRangeCollection == null) { throw new ArgumentNullException("pieceIndexRangeCollection"); } Helper.CheckCondition(batchCount > 0, string.Format(CultureInfo.CurrentCulture, Properties.Resource.BatchCountCondition)); long pieceIndex = 0; long batchIndex = 0; bool inRange = pieceIndexRangeCollection.Contains(pieceIndex); foreach (var tAndRowIndex in UseSkipList(enumerable, skipListOrNull)) { if (inRange) { yield return(tAndRowIndex); } ++batchIndex; if (batchIndex == batchCount) { batchIndex = 0; pieceIndex = (pieceIndex + 1) % pieceCount; inRange = pieceIndexRangeCollection.Contains(pieceIndex); } } }
public void RunTasks(Bio.Util.RangeCollection tasksToRun, long taskCount) { throw new NotImplementedException(); }