Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 加上或减去一组范围,如;1,2,4,10-25,40+&引用+&引用;“3,11,26”;_C#_Collections_Range - Fatal编程技术网

C# 加上或减去一组范围,如;1,2,4,10-25,40+&引用+&引用;“3,11,26”;

C# 加上或减去一组范围,如;1,2,4,10-25,40+&引用+&引用;“3,11,26”;,c#,collections,range,C#,Collections,Range,我正在编写一个C#程序,用户可以在其中输入一系列值,比如“1,2,4,10-25,40+”,其中项目可以是单个数字,范围可以是10-25,范围可以是无穷大,比如25+。范围必须至少相隔2,不能说是10-11,应该是10,11。 我需要函数来加减它们 例如,“1,2,4,10-25,40+”+“3,11,26”将返回“1-4,10-26,40+” 我在这里使用字符串作为示例,但假设数据已经被解析为三个类别的对象:单个数字、范围、无限范围。我不是在问如何解析字符串 我正在编写自己的函数集,并且看到由

我正在编写一个C#程序,用户可以在其中输入一系列值,比如“1,2,4,10-25,40+”,其中项目可以是单个数字,范围可以是10-25,范围可以是无穷大,比如25+。范围必须至少相隔2,不能说是10-11,应该是10,11。 我需要函数来加减它们

例如,“1,2,4,10-25,40+”+“3,11,26”将返回“1-4,10-26,40+”

我在这里使用字符串作为示例,但假设数据已经被解析为三个类别的对象:单个数字、范围、无限范围。我不是在问如何解析字符串

我正在编写自己的函数集,并且看到由于范围必须相隔2,因此存在很多复杂性。我知道有一些函数可以测试一个数字是否在一个范围内,这很容易构建到一个例程中来测试一个数字是否在一组范围内


但是我如何加或减集合,并简化它们,这样你就不会得到11,12,13,而是11-13了?这不是小事。我对任何解决方案都持开放态度,如果需要,我可以导入库。

您提示有三个不同的类代表三种不同类型的范围。我希望您有一个聚合范围集合类?如果没有,创建一个。下面是一个伪代码算法,用于在向现有集合添加新集合时执行的操作:

Add(范围集合集合2)
对于collection2.singles中的每个int n
如果n>=无限范围开始:下一个n
//应该只有一个无限范围
对于ranges//ranges中的每个range r,ranges应该是一个排序列表
如果n=r,则启动-1
r、 开始=n
下一个
如果n=r.end+1
r、 结束=n
下一个
如果n=r.start和n start+1
范围。添加(新范围(开始、结束))
开始=空
end=null
如果开始空和结束!=null和end>start+1
范围。添加(新范围(开始、结束))
合并重叠范围()
//范围应该是按range.start排序的范围对象列表
prevR=null
对于范围中的每个范围r
如果prevR=null
prevR=r
下一个r
如果prevR.end>=r.start
prevR.end=r.end
范围。删除(r)
下一个r
prevR=r
CheckInfiniteRange()
如果singles.max=inifinite\u range\u start-1
在有限范围内启动--
CheckInfiniteRange()
如果ranges.last.end>=INIFimited\u range\u start-1
inifinite\u range\u start=ranges.last.start
范围。删除(范围。最后一个)
singles.RemoveAll(其中n>=无限范围\u开始)
CheckInfiniteRange()
减去(范围集合集合2)
对于collection2.singles中的每个数字n
if singles.Contains(n)
单打。删除(n)
下一个
对于范围中的每个范围r
如果n=r,则启动
r、 开始++
下一个
如果n=r.end
r、 结束--
下一个
如果n>r.开始和n无限范围\u开始
添加(新范围(无限范围开始,n-1))
无限范围开始=n+1
下一个
注:

  • 我只展示了如何处理单个数字。我把它作为一个练习留给你们去扩展它来处理范围。这应该不难理解
  • 我没有费心包括基本的防御,比如检查空值或空集。你会想要的
  • 我已经做出了我认为合理的假设,关于你的三个范围类暴露的属性
  • 在一些地方,一个朴素的实现会在遍历列表时从列表中删除一个元素,从而导致运行时错误。您的实现需要考虑到这一点;这样做应该很容易
  • 这对于负数是鲁棒的,但只允许增加无限范围(向正无穷方向移动)。例如,“10-”(表示从10向下到负无穷大)不是有效范围。如果您需要无限范围代码的功能,镜像该代码相对简单

    • 我写了一个小函数来帮助您

      一小条
      这是我的函数集。 我将序列项定义为整数列表(所有正的BTW),其中单个num为(num),范围为(start-end),无限范围为(num-1)。 在字符串中,我允许-或|作为范围分隔符。 我可能遗漏了一些扩展方法,但我想我得到了它们。 我知道这些空间在网上看起来很难看,你需要复制并粘贴到一个.cs文件中才能看得清楚。我从VS复制并粘贴了jsut

      要进行测试,请尝试以下内容:(它们故意具有奇数值…)

      列表>结果=添加序列(StringToSequence(“10,11,12-14,20-30,40+”),StringToSequence(“15,16,21-41,50+”)

      列表>结果=减去序列(StringToSequence(“10,11,20-30,40+”),StringToSequence(“21-41,50+”))

      列表>结果=字符串序列(“1-5,8,10,11-29,30+,19-25,30-40,50+,60+”

      /--------------序列工具-----------------------------
      公共静态字符串SequenceToString(列表顺序){
      字符串ret=“”;
      foreach(序列中的列表对){
      if(pair.Count==1)
      ret=ret+pair[0].ToString()+“,”;
      否则{
      如果(对[1]!=-1)
      ret=ret+pair[0]。ToString()+“|”+pair[1]。ToString()+”,”;
      其他的
      ret=ret+pair[0]。ToString()
      
      private static List<string> Simplify(List<string> inputs)
      {
          var simpleList = new List<int>();
          var retval = new List<string>();
          bool infinity = false;
      
          foreach (string input in inputs)
          {
              if (string.IsNullOrEmpty(input))
                  continue;
      
              if (input.Split('-').Length > 1)
              {
                  int min = int.Parse(input.Split('-')[0].Trim());
                  int max = int.Parse(input.Split('-')[1].Trim());
      
                  // inclusive
                  simpleList.AddRange(Enumerable.Range(min, max - min + 1));
      
                  continue;
              }
      
              if (input.Trim().EndsWith("+"))
              {
                  infinity = true;
                  simpleList.Add(int.Parse(input.Trim().Trim('+')));
              } else simpleList.Add(int.Parse(input.Trim()));
          }
      
          simpleList.Sort();
      
          for (int i = 0; i < simpleList.Count; i++)
          {
              int currentVal = simpleList[i];
              int q = i;
              while (q < simpleList.Count)
              {
                  if (q != simpleList.Count - 1 && simpleList[q] + 1 == simpleList[q + 1])
                  {
                      q++;
                      continue;
                  }
                  if (currentVal == simpleList[q])
                  {
                      retval.Add(currentVal.ToString());
                      i = q;
                      break;
                  }
                  if (currentVal + 1 == simpleList[q])
                  {
                      retval.Add(currentVal.ToString());
                      retval.Add(simpleList[q].ToString());
                      i = q;
                      break;
                  }
                  retval.Add(currentVal + "-" + simpleList[q]);
                  i = q;
                  break;
              }
          }
      
          if (infinity)
              retval[retval.Count - 1] = retval[retval.Count - 1] + "+";
      
          return retval;
      }
      
      var inputs = new List<string> {"11", "12", "13", "14-18", "2-3", "25", "82+", "9"};
      
      var simplifiedList = Simplify(inputs);
      
      foreach (string input in simplifiedList)
      {
          Console.WriteLine(input);
      }
      
      2
      3
      9
      11-18
      25
      82+
      
          //-------------------sequence tools-----------------------------
          public static string SequenceToString(List<List<int>> seq) {
          string ret = "";
          foreach (List<int> pair in seq) {
              if (pair.Count == 1)
              ret = ret + pair[0].ToString() + ",";
              else {
              if (pair[1] != -1)
                  ret = ret + pair[0].ToString() + "|" + pair[1].ToString() + ",";
              else
                  ret = ret + pair[0].ToString() + "+,";
              }
          }
          return ret;
          }
      
      public static List<List<int>> StringToSequence(string seq) {
          List<List<int>> ret = new List<List<int>>();
          //make sure we have a list of integers
          //turn into a List<List<int>>
          //use -1 as second item to indicate the +
          List<List<int>> pairs = new List<List<int>>();
          //int usesPlus = -1;
          //split by commas
          string[] items = seq.RemoveCharsExcept("|.,-+").Split(',');
          foreach (string str in items) {
          //see if we have a dash
          if (str.Contains("-") || str.Contains("|")) {
              string[] tmp1;
              if (str.Contains("-"))
              tmp1 = str.Split('-');
              else 
              tmp1 = str.Split('|');
              //the RemoveChars() is to get rid of a + if there
              if (tmp1.Count() == 2 && tmp1[0].RemoveChars().IsInteger() && tmp1[1].RemoveChars().IsInteger()) {
              int int1 = tmp1[0].RemoveChars().ToInteger();
              int int2 = tmp1[1].RemoveChars().ToInteger();
              if (int2 > int1)
                  if (int2 - int1 == 1) {
                  pairs.Add(new List<int>() { int1 });
                  pairs.Add(new List<int>() { int2 });
                  }
                  else
                  pairs.Add(new List<int>() { int1, int2 });
              }
          }
          else if (str.RemoveChars().IsInteger()) {
              int tmp = str.RemoveChars().ToInteger();
              if (str.Right(1) == "+")
              pairs.Add(new List<int>() { str.RemoveChars().ToInteger(), -1 });
              else
              pairs.Add(new List<int>() { str.RemoveChars().ToInteger() });
          }
          }
          //now sort list by first item
          ret = pairs.OrderBy(o => o[0]).ToList();
          DelSequenceDupes(ret);
          CombineSequenceNums(ret);
          CombineSequenceMergeNumsToSeqs(ret);
          CombineSequenceSeqs(ret);
          TrimSequenceByPlusNums(ret);
          return ret;
      }
      
      //all these assume items are in order by first element
      public static List<List<int>> AddSequences(List<List<int>> origSeq, List<List<int>> addSeq) {
          List<List<int>> ret = new List<List<int>>();
          //add in items and clean up
          origSeq.AddRange(addSeq);
          //sort list by first item
          ret = origSeq.OrderBy(o => o[0]).ToList();
          DelSequenceDupes(ret);
          CombineSequenceNums(ret);
          CombineSequenceMergeNumsToSeqs(ret);
          CombineSequenceSeqs(ret);
          TrimSequenceByPlusNums(ret);
          return ret;
      }
      
      public static List<List<int>> DelSequenceDupes(List<List<int>> seq) {
          List<List<int>> ret = new List<List<int>>();
          List<int> prev = new List<int>();
          foreach (List<int> pair in seq) {
          if (prev.Count == 0) {
              ret.Add(pair);
              prev = pair;
          }
          else if (prev.Count != pair.Count || prev[0] != pair[0] || prev[1] != pair[1]) {
              ret.Add(pair);
              prev = pair;
          }
          }
          return ret;
      }
      
      public static List<List<int>> CombineSequenceNums(List<List<int>> seq) {
          List<List<int>> ret = new List<List<int>>();
          int conscount = 0;
          int previtem = -1;
          foreach (List<int> pair in seq) {
          if (pair.Count == 1) {
              if (conscount == 0) {
              previtem = pair[0];
              conscount++;
              }
              else {
              if (pair[0] == previtem + 1) {
                  previtem = pair[0];
                  conscount++;
              }
              //else deal with any sequences or not, and start over
              else {
                  if (conscount < 3) {
                  for (int i = conscount - 1; i >= 0; i--) {
                      ret.Add(new List<int>() { previtem - i });
                  }
                  }
                  //else its a sequence
                  else {
                  ret.Add(new List<int>() { previtem - (conscount - 1), previtem });
                  }
                  //start over on this number
                  previtem = pair[0];
                  conscount = 1;
              }
              }
          }
          else {
              //if on a sequence, see if conscount is more than 2
              if (conscount < 3) {
              for (int i = conscount - 1; i >= 0; i--) {
                  ret.Add(new List<int>() { previtem - i });
              }
              }
              //else its a sequence
              else {
              ret.Add(new List<int>() { previtem - (conscount - 1), previtem });
              }
              //start over on bogus previtem
              previtem = -1;
              conscount = 0;
              //now add the sequence as is
              ret.Add(pair);
          }
          }
          //add any hanging numbers
          //if on a sequence, see if conscount is more than 2
          if (conscount < 3) {
          for (int i = conscount - 1; i >= 0; i--) {
              ret.Add(new List<int>() { previtem - i });
          }
          }
          //else its a sequence
          else {
          ret.Add(new List<int>() { previtem - (conscount - 1), previtem });
          }
          return ret;
      }
      
      public static List<List<int>> CombineSequenceSeqs(List<List<int>> seq) {
          List<List<int>> ret = new List<List<int>>();
          List<int> prevseq = new List<int>();
          foreach (List<int> pair in seq) {
          if (pair.Count == 1) {
              //add previous sequence if any
              if (prevseq.Count > 0) {
              ret.Add(prevseq);
              prevseq = new List<int>();
              }
              ret.Add(pair);
          }
          //else if a sequence
          else {
              if (pair[1] == -1) {
              //add previous sequence if any
              if (prevseq.Count > 0) {
                  ret.Add(prevseq);
                  prevseq = new List<int>();
              }
              ret.Add(pair);
              }
              else {
              if (prevseq.Count == 0) {
                  prevseq = pair;
              }
              //if adjacent or any overlap, combine
              else {
                  if (prevseq[1] + 1 >= pair[0]) {
                  prevseq = new List<int>() { prevseq[0], Math.Max(pair[1], prevseq[1]) };
                  }
                  else {
                  ret.Add(prevseq);
                  prevseq = pair;
                  }
              }
              }
          }
          }
          //add at end
          if (prevseq.Count > 0)
          ret.Add(prevseq);
          return ret;
      }
      
      public static List<List<int>> CombineSequenceMergeNumsToSeqs(List<List<int>> seq) {
          List<List<int>> ret = new List<List<int>>();
          int index = 0;
          while (index < seq.Count) {
          List<int> pair = seq[index];
          //if a number, add to ret
          if (pair.Count == 1 || (pair.Count == 2 && pair[1] == -1)) {
              ret.Add(pair);
              index++;
          }
          else {
              //if on a seq, look behind and ahead for numbers to gobble
              int lookback = 1;
              List<int> newpair = pair;
              bool go = true;
              while (go &&
                 index > 0 &&
                 index - lookback > -1) {
              if (seq[index - lookback].Count == 1 &&
                  seq[index - lookback][0] == newpair[0] - 1) {
                  //remove last item from ret
                  ret.RemoveAt(ret.Count - 1);
                  //modify newpair
                  newpair[0] = newpair[0] - 1;
                  lookback++;
              }
              else
                  go = false;
              }
              //now look ahead, careful to get rid of item in the range already
              int lookahd = 1;
              go = true;
              while (go &&
                 index < seq.Count + 1 &&
                 index + lookahd < seq.Count) {
              if (seq[index + lookahd].Count == 1) {
                  //if in range already
                  if (seq[index + lookahd][0] <= newpair[1])
                  lookahd++;
                  else if (seq[index + lookahd][0] == newpair[1] + 1) {
                  //modify newpair
                  newpair[1] = newpair[1] + 1;
                  lookahd++;
                  }
                  else
                  go = false;
              }
              else
                  go = false;
              }
              //add newpair to ret
              ret.Add(newpair);
              //jump past items done
              index = index + lookahd;
          }
          }
          return ret;
      }
      
      public static List<List<int>> TrimSequenceByPlusNums(List<List<int>> seq) {
          List<List<int>> ret = new List<List<int>>();
          //get sequence info
          int lowPlsNum;
          int highest = FindHighestInSeq(seq, out lowPlsNum);
          if (lowPlsNum != -1) {
          foreach (List<int> pair in seq) {
              if (pair.Count == 1) {
              if (pair[0] < lowPlsNum)
                  ret.Add(pair);
              }
              else {
              if (pair[1] == -1) {
                  if (pair[0] == lowPlsNum)
                  ret.Add(pair);
              }
              else {
                  if (pair[1] < lowPlsNum) {
                  ret.Add(pair);
                  }
                  else if (pair[0] < lowPlsNum && pair[1] >= lowPlsNum)
                  ret.Add(new List<int>() { pair[0], lowPlsNum - 1 });
              }
              }
          }
          }
          else
          ret = seq;
          return ret;
      }
      
      //assumes subtSeq has been cleaned so items are in order
      public static List<List<int>> SubtractSequences(List<List<int>> origSeq, List<List<int>> subtSeq) {
          List<List<int>> ret = new List<List<int>>();
          if (subtSeq.Count > 0) {
          //go through origSeq and modify any items
          foreach (List<int> pair in origSeq) {
              //case 1 - just one number
              if (pair.Count == 1) {
              if (!IsPtInSequence(subtSeq, pair[0]))
                  //add if not in subt sequence
                  ret.Add(pair);
              }
              //case 2 - a sequence in orig
              else if (pair.Count == 2 && pair[1] != -1) {
              //must chop up based on items in subt
              List<List<int>> res = SubtractFromNonPlusSequence(pair, subtSeq);
              if (res.Count > 0)
                  ret.AddRange(res);
              }
              //a number+
              else if (pair.Count == 2 && pair[1] == -1) {
              List<List<int>> res = SubtractFromPlusSequence(pair, subtSeq);
              if (res.Count > 0)
                  ret.AddRange(res);
              }
          }
          }
          return ret;
      }
      //subtract a num+ by sequence
      //origSeq  must have a -1 as second item
      public static List<List<int>> SubtractFromPlusSequence(List<int> origSeq, List<List<int>> subtSeq) {
          List<List<int>> ret = new List<List<int>>();
          //handle by converting the num+ to a sequence plus a num+ if needed
          //find largest number in subtSeq
          int lowPlsNum;
          int largest = FindHighestInSeq(subtSeq, out lowPlsNum);
          List<int> tmpseq;
          //now make temp sequence
          if (lowPlsNum == -1) {
          //return original as its all before
          if (largest < origSeq[0]) {
              ret = new List<List<int>>() { origSeq };
          }
          else {
              //if overlap of 1
              if (largest - origSeq[0] == 1) {
              if (!IsPtInSequence(subtSeq, origSeq[0]))
                  ret.Add(new List<int>() { origSeq[0] });
              }
              else if (largest - origSeq[0] == 2) {
              if (!IsPtInSequence(subtSeq, origSeq[0]))
                  ret.Add(new List<int>() { origSeq[0] });
              if (!IsPtInSequence(subtSeq, origSeq[0] + 1))
                  ret.Add(new List<int>() { origSeq[0] + 1 });
              }
              else {
              tmpseq = new List<int>() { origSeq[0], largest - 1 };
              ret.AddRange(SubtractFromNonPlusSequence(tmpseq, subtSeq));
              }
              //add a plus after all, since subtSeq did not have a +num in it
              ret.Add(new List<int>() { largest + 1, -1 });
          }
          }
          else {
          //its got a plus in it, just do before the subtract +
          if (lowPlsNum - origSeq[0] == 1) {
              ret.Add(new List<int>() { origSeq[0] });
          }
          else if (lowPlsNum - origSeq[0] == 2) {
              ret.Add(new List<int>() { origSeq[0] });
              ret.Add(new List<int>() { origSeq[0] + 1 });
          }
          else {
              tmpseq = new List<int>() { origSeq[0], lowPlsNum - 1 };
              ret.AddRange(SubtractFromNonPlusSequence(tmpseq, subtSeq));
          }
          //else return blank as it got wiped out
          }
          return ret;
      }
      
      //subtract a sequence (2 items) using another
      public static List<List<int>> SubtractFromNonPlusSequence(List<int> origSeq, List<List<int>> subtSeq) {
          List<List<int>> ret = new List<List<int>>();
          //as we go along, curseq will be the term at hand to possibly chop
          List<int> curseq = origSeq;
          bool done = false;
          foreach (List<int> chopr in subtSeq) {
          if (!done) {
              //if chopping with one number
              if (chopr.Count == 1) {
              #region Chop with one
              //test if chop at all
              if (chopr[0] < curseq[0] || chopr[0] > curseq[1]) {
                  ret.Add(curseq);
                  done = true;
              }
              else {
                  //handle left side of chop
                  if (chopr[0] - curseq[0] == 1) {
                  ret.Add(new List<int>() { curseq[0] });
                  }
                  else if (chopr[0] - curseq[0] == 2) {
                  ret.Add(new List<int>() { curseq[0] });
                  ret.Add(new List<int>() { curseq[0] + 1 });
                  }
                  else if (chopr[0] - curseq[0] > 2) {
                  ret.Add(new List<int>() { curseq[0], chopr[0] - 1 });
                  }
                  //handle right side of chop
                  if (curseq[1] - chopr[0] == 1) {
                  ret.Add(new List<int>() { curseq[1] });
                  done = true;
                  }
                  else if (curseq[1] - chopr[0] == 2) {
                  ret.Add(new List<int>() { curseq[1] - 1 });
                  ret.Add(new List<int>() { curseq[1] });
                  done = true;
                  }
                  else if (curseq[1] - chopr[0] > 2) {
                  curseq = new List<int>() { chopr[0] + 1, curseq[1] };
                  }
              }
              }
              #endregion
              //now look at a chopper sequence
              else {
              //if a number +
              if (chopr[1] == -1) {
                  #region Chop with one+
                  //only 3 cases matter
                  //if at or before start
                  if (chopr[0] <= curseq[0]) {
                  //stop
                  done = true;
                  }
                  else if (chopr[0] > curseq[1]) {
                  //do nothing
                  }
                  //if past start by 1
                  else if (chopr[0] == curseq[0] + 1) {
                  ret.Add(new List<int>() { curseq[0] });
                  done = true;
                  }
                  //if past start by 2
                  else if (chopr[0] == curseq[0] + 2) {
                  ret.Add(new List<int>() { curseq[0] });
                  ret.Add(new List<int>() { curseq[0] + 1 });
                  //stop here because discard the rest
                  done = true;
                  }
                  //if past start by more than 2
                  else {
                  ret.Add(new List<int>() { curseq[0], chopr[0] - 1 });
                  done = true;
                  }
              }
                  #endregion
              //if a sequence
              else {
                  #region Chop with seq
                  //complete overlap
                  if (curseq[0] >= chopr[0] && curseq[1] <= chopr[1]) {
                  done = true;
                  }
                  //if we overlap chop start
                  else if (chopr[1] == curseq[0]) {
                  curseq = new List<int>() { curseq[0] + 1, curseq[1] };
                  }
                  //if we overlap chop end
                  else if (chopr[0] == curseq[1]) {
                  curseq = new List<int>() { curseq[0], curseq[1] - 1 };
                  }
                  //if we enclose chopper
                  else if (chopr[0] > curseq[0] && chopr[1] < curseq[1]) {
                  //handle left side
                  if (chopr[0] - curseq[0] == 1) {
                      ret.Add(new List<int>() { curseq[0] });
                  }
                  else if (chopr[0] - curseq[0] == 2) {
                      ret.Add(new List<int>() { curseq[0] });
                      ret.Add(new List<int>() { curseq[0] + 1 });
                  }
                  else {
                      ret.Add(new List<int>() { curseq[0], chopr[0] - 1 });
                  }
                  //handle right side
                  if (curseq[1] - chopr[1] == 1) {
                      ret.Add(new List<int>() { curseq[1] });
                      done = true;
                  }
                  else if (curseq[1] - chopr[1] == 2) {
                      ret.Add(new List<int>() { curseq[1] - 1 });
                      ret.Add(new List<int>() { curseq[1] });
                      done = true;
                  }
                  else {
                      curseq = new List<int>() { chopr[1] + 1, curseq[1] };
                  }
                  }
                  //if we overlap past chop start
                  else if (chopr[0] < curseq[0] && chopr[1] > curseq[0] && chopr[1] < curseq[1]) {
                  //see if we leave nums or a sequence
                  if (curseq[1] - chopr[1] == 1) {
                      ret.Add(new List<int>() { curseq[1] });
                      done = true;
                  }
                  else if (curseq[1] - chopr[1] == 2) {
                      ret.Add(new List<int>() { curseq[1] - 1 });
                      ret.Add(new List<int>() { curseq[1] });
                      done = true;
                  }
                  else {
                      curseq = new List<int>() { chopr[1] + 1, curseq[1] };
                  }
                  }
                  //if we overlap before chop end
                  else if (chopr[0] > curseq[0] && chopr[0] < curseq[1] && chopr[1] >= curseq[1]) {
                  //see if we leave nums or a sequence
                  if (chopr[0] - curseq[0] == 1) {
                      ret.Add(new List<int>() { curseq[0] });
                      done = true;
                  }
                  else if (chopr[0] - curseq[0] == 2) {
                      ret.Add(new List<int>() { curseq[0] });
                      ret.Add(new List<int>() { curseq[0] + 1 });
                      done = true;
                  }
                  else {
                      ret.Add(new List<int>() { curseq[0], chopr[0] - 1 });
                      done = true;
                  }
                  }
              }
                  #endregion
              }
          }
          }
          if (!done)
          ret.Add(curseq);
          return ret;
      }
      
      //find highest number in sequence, as well as lowest +num if an
      //lowPlsNum is -1 if not found
      public static int FindHighestInSeq(List<List<int>> seq, out int lowPlsNum) {
          //find largest number in subtSeq
          int ret = 0;
          //track lowest num+ if found in subtSeq
          lowPlsNum = -1;
          foreach (List<int> pair in seq) {
          if (pair.Count == 1) {
              if (pair[0] > ret)
              ret = pair[0];
          }
          else if (pair.Count == 2 && pair[1] != -1) {
              if (pair[1] > ret)
              ret = pair[1];
          }
          else if (pair.Count == 2 && pair[1] == -1) {
              if (lowPlsNum == -1)
              lowPlsNum = pair[0];
              if (pair[0] < lowPlsNum)
              lowPlsNum = pair[0];
          }
          }
          return ret;
      }
      
      public static bool IsPtInSequence(List<List<int>> seq, int ptnum) {
          bool ret = false;
          foreach (List<int> lst in seq) {
          if (lst.Count == 1) {
              if (lst[0] == ptnum)
              ret = true;
          }
          else if (lst.Count == 2) {
              //check if plus item
              if (lst[1] == -1) {
              if (ptnum >= lst[0])
                  ret = true;
              }
              else if (ptnum >= lst[0] && ptnum <= lst[1])
              ret = true;
          }
          }
          return ret;
      }
      
      public static string RemoveChars(this string s) {
          string str = "";
          foreach (char c in s) {
              if (char.IsDigit(c) || c == '.' || c == ',' || c == '-') {
                  str = str + c.ToString();
              }
          }
          return str;
      }
      
      //keep is list of single chars
      public static string RemoveCharsExcept(this string s, string keep) {
          string str = "";
          foreach (char c in s) {
          if (char.IsDigit(c) || keep.Contains(c)) {
              str = str + c.ToString();
          }
          }
          return str;
      }
      
      /// <summary>
      /// Returns the last few characters of the string with a length
      /// specified by the given parameter. If the string's length is less than the 
      /// given length the complete string is returned. If length is zero or 
      /// less an empty string is returned
      /// </summary>
      /// <param name="s">the string to process</param>
      /// <param name="length">Number of characters to return</param>
      /// <returns></returns>
      public static string Right(this string s, int length) {
          length = Math.Max(length, 0);
          if (s.Length > length) {
              return s.Substring(s.Length - length, length);
          }
          else {
              return s;
          }
      }
      
      /// <summary>
      /// Returns the first few characters of the string with a length
      /// specified by the given parameter. If the string's length is less than the 
      /// given length the complete string is returned. If length is zero or 
      /// less an empty string is returned
      /// </summary>
      /// <param name="s">the string to process</param>
      /// <param name="length">Number of characters to return</param>
      /// <returns></returns>
      public static string Left(this string s, int length) {
          length = Math.Max(length, 0);
      
          if (s.Length > length) {
              return s.Substring(0, length);
          }
          else {
              return s;
          }
      }
      public static string StripLeft(this string s, int length) {
          length = Math.Max(length, 0);
      
          if (s.Length > length) {
              return s.Substring(length);
          }
          else {
              return "";
          }
      }
      public static string StripRight(this string s, int length) {
          length = Math.Max(length, 0);
      
          if (s.Length > length) {
              return s.Substring(0, s.Length - length);
          }
          else {
              return "";
          }
      }