interval.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //
  2. // assembly: System
  3. // namespace: System.Text.RegularExpressions
  4. // file: interval.cs
  5. //
  6. // author: Dan Lewis ([email protected])
  7. // (c) 2002
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections;
  30. namespace System.Text.RegularExpressions {
  31. struct Interval : IComparable {
  32. public int low;
  33. public int high;
  34. public bool contiguous;
  35. public static Interval Empty {
  36. get {
  37. Interval i;
  38. i.low = 0;
  39. i.high = i.low - 1;
  40. i.contiguous = true;
  41. return i;
  42. }
  43. }
  44. public static Interval Entire {
  45. get { return new Interval (Int32.MinValue, Int32.MaxValue); }
  46. }
  47. public Interval (int low, int high) {
  48. if (low > high) {
  49. int t = low;
  50. low = high;
  51. high = t;
  52. }
  53. this.low = low;
  54. this.high = high;
  55. this.contiguous = true;
  56. }
  57. public bool IsDiscontiguous {
  58. get { return !contiguous; }
  59. }
  60. public bool IsSingleton {
  61. get { return contiguous && low == high; }
  62. }
  63. public bool IsRange {
  64. get { return !IsSingleton && !IsEmpty; }
  65. }
  66. public bool IsEmpty {
  67. get { return low > high; }
  68. }
  69. public int Size {
  70. get {
  71. if (IsEmpty)
  72. return 0;
  73. return high - low + 1;
  74. }
  75. }
  76. public bool IsDisjoint (Interval i) {
  77. if (IsEmpty || i.IsEmpty)
  78. return true;
  79. return !(low <= i.high && i.low <= high);
  80. }
  81. public bool IsAdjacent (Interval i) {
  82. if (IsEmpty || i.IsEmpty)
  83. return false;
  84. return low == i.high + 1 || high == i.low - 1;
  85. }
  86. public bool Contains (Interval i) {
  87. if (!IsEmpty && i.IsEmpty)
  88. return true;
  89. if (IsEmpty)
  90. return false;
  91. return low <= i.low && i.high <= high;
  92. }
  93. public bool Contains (int i) {
  94. return low <= i && i <= high;
  95. }
  96. public bool Intersects (Interval i) {
  97. if (IsEmpty || i.IsEmpty)
  98. return false;
  99. return ((Contains (i.low) && !Contains (i.high)) ||
  100. (Contains (i.high) && !Contains (i.low)));
  101. }
  102. public void Merge (Interval i) {
  103. if (i.IsEmpty)
  104. return;
  105. if (IsEmpty) {
  106. this.low = i.low;
  107. this.high = i.high;
  108. }
  109. if (i.low < low)
  110. low = i.low;
  111. if (i.high > high)
  112. high = i.high;
  113. }
  114. public void Intersect (Interval i) {
  115. if (IsDisjoint (i)) {
  116. low = 0;
  117. high = low - 1;
  118. return;
  119. }
  120. if (i.low > low)
  121. low = i.low;
  122. if (i.high > high)
  123. high = i.high;
  124. }
  125. public int CompareTo (object o) {
  126. return low - ((Interval)o).low;
  127. }
  128. public new string ToString () {
  129. if (IsEmpty)
  130. return "(EMPTY)";
  131. else if (!contiguous)
  132. return "{" + low + ", " + high + "}";
  133. else if (IsSingleton)
  134. return "(" + low + ")";
  135. else
  136. return "(" + low + ", " + high + ")";
  137. }
  138. }
  139. class IntervalCollection : ICollection, IEnumerable {
  140. public IntervalCollection () {
  141. intervals = new ArrayList ();
  142. }
  143. public Interval this[int i] {
  144. get { return (Interval)intervals[i]; }
  145. set { intervals[i] = value; }
  146. }
  147. public void Add (Interval i) {
  148. intervals.Add (i);
  149. }
  150. public void Clear () {
  151. intervals.Clear ();
  152. }
  153. public void Sort () {
  154. intervals.Sort ();
  155. }
  156. public void Normalize () {
  157. intervals.Sort ();
  158. int j = 0;
  159. while (j < intervals.Count - 1) {
  160. Interval a = (Interval)intervals[j];
  161. Interval b = (Interval)intervals[j + 1];
  162. if (!a.IsDisjoint (b) || a.IsAdjacent (b)) {
  163. a.Merge (b);
  164. intervals[j] = a;
  165. intervals.RemoveAt (j + 1);
  166. }
  167. else
  168. ++ j;
  169. }
  170. }
  171. public delegate double CostDelegate (Interval i);
  172. public IntervalCollection GetMetaCollection (CostDelegate cost_del) {
  173. IntervalCollection meta = new IntervalCollection ();
  174. Normalize ();
  175. Optimize (0, Count - 1, meta, cost_del);
  176. meta.intervals.Sort ();
  177. return meta;
  178. }
  179. private void Optimize (int begin, int end, IntervalCollection meta, CostDelegate cost_del) {
  180. Interval set;
  181. set.contiguous = false;
  182. int best_set_begin = -1;
  183. int best_set_end = -1;
  184. double best_set_cost = 0;
  185. for (int i = begin; i <= end; ++ i) {
  186. set.low = this[i].low;
  187. double cost = 0.0;
  188. for (int j = i; j <= end; ++ j) {
  189. set.high = this[j].high;
  190. cost += cost_del (this[j]);
  191. double set_cost = cost_del (set);
  192. if (set_cost < cost && cost > best_set_cost) {
  193. best_set_begin = i;
  194. best_set_end = j;
  195. best_set_cost = cost;
  196. }
  197. }
  198. }
  199. if (best_set_begin < 0) {
  200. // didn't find an optimal set: add original members
  201. for (int i = begin; i <= end; ++ i)
  202. meta.Add (this[i]);
  203. }
  204. else {
  205. // found set: add it ...
  206. set.low = this[best_set_begin].low;
  207. set.high = this[best_set_end].high;
  208. meta.Add (set);
  209. // ... and optimize to the left and right
  210. if (best_set_begin > begin)
  211. Optimize (begin, best_set_begin - 1, meta, cost_del);
  212. if (best_set_end < end)
  213. Optimize (best_set_end + 1, end, meta, cost_del);
  214. }
  215. }
  216. // ICollection implementation
  217. public int Count {
  218. get { return intervals.Count; }
  219. }
  220. public bool IsSynchronized {
  221. get { return false; }
  222. }
  223. public object SyncRoot {
  224. get { return intervals; }
  225. }
  226. public void CopyTo (Array array, int index) {
  227. foreach (Interval i in intervals) {
  228. if (index > array.Length)
  229. break;
  230. array.SetValue (i, index ++);
  231. }
  232. }
  233. // IEnumerator implementation
  234. public IEnumerator GetEnumerator () {
  235. return new Enumerator (intervals);
  236. }
  237. private class Enumerator : IEnumerator {
  238. public Enumerator (IList list) {
  239. this.list = list;
  240. Reset ();
  241. }
  242. public object Current {
  243. get {
  244. if (ptr >= list.Count)
  245. throw new InvalidOperationException ();
  246. return list[ptr];
  247. }
  248. }
  249. public bool MoveNext () {
  250. if (ptr > list.Count)
  251. throw new InvalidOperationException ();
  252. return ++ ptr < list.Count;
  253. }
  254. public void Reset () {
  255. ptr = -1;
  256. }
  257. private IList list;
  258. private int ptr;
  259. }
  260. // private fields
  261. private ArrayList intervals;
  262. }
  263. }