Skip to main content

disjoint_intervals/
lib.rs

1use std::{
2    collections::BTreeMap,
3    fmt::{self, Debug},
4    ops::Range,
5};
6
7/// 互いに素な区間を管理するデータ構造
8#[derive(Clone, PartialEq, Eq)]
9pub struct DisjointIntervals<T> {
10    // [start, end)
11    intervals: BTreeMap<T, T>,
12}
13
14/// 区間を挿入したときに触った各部分区間の状態を表す
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum InsertItem<T> {
17    /// 新しく挿入された区間
18    New(Range<T>),
19    /// 既存の区間と重なった区間
20    Overlap(Range<T>),
21}
22
23/// 区間を削除したときに触った各部分区間の状態を表す
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum RemoveItem<T> {
26    /// 削除された区間
27    Remove(Range<T>),
28    /// 元々存在しなかった区間
29    Absent(Range<T>),
30}
31
32impl<T> DisjointIntervals<T>
33where
34    T: Ord + Clone + Copy,
35{
36    pub fn new() -> Self {
37        Self {
38            intervals: BTreeMap::new(),
39        }
40    }
41
42    pub fn len(&self) -> usize {
43        self.intervals.len()
44    }
45
46    pub fn is_empty(&self) -> bool {
47        self.intervals.is_empty()
48    }
49
50    pub fn iter(&self) -> impl Iterator<Item = Range<T>> {
51        self.intervals.iter().map(|(&start, &end)| start..end)
52    }
53
54    /// 区間を追加する
55    ///
56    /// 初期値 `init`, 関数 `f` による畳み込み結果を返す
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use disjoint_intervals::{DisjointIntervals, InsertItem};
62    ///
63    /// let mut intervals = DisjointIntervals::<i32>::new();
64    /// intervals.insert(-10..5, (), |_, _| ());
65    /// let overlapped = intervals.insert(0..10, 0, |acc, item| {
66    ///     if let InsertItem::Overlap(item) = item {
67    ///        acc + (item.end - item.start)
68    ///     } else {
69    ///        acc
70    ///     }
71    /// });
72    /// assert_eq!(overlapped, 5);
73    ///
74    /// assert_eq!(intervals.iter().collect::<Vec<_>>(), vec![-10..10]);
75    /// ```
76    pub fn insert<U, F>(&mut self, interval: Range<T>, init: U, f: F) -> U
77    where
78        F: FnMut(U, InsertItem<T>) -> U,
79    {
80        assert!(!interval.is_empty());
81
82        let mut acc = init;
83        let mut f = f;
84        let (insert_start, mut start, insert_end) =
85            match self.intervals.range(..=interval.start).last() {
86                Some((&prev_start, &prev_end)) if interval.start <= prev_end => {
87                    if interval.start < prev_end {
88                        let overlap_end = prev_end.min(interval.end);
89                        acc = f(acc, InsertItem::Overlap(interval.start..overlap_end));
90                    }
91                    self.intervals.remove(&prev_start);
92                    (
93                        prev_start,
94                        prev_end.max(interval.start),
95                        interval.end.max(prev_end),
96                    )
97                }
98                _ => (interval.start, interval.start, interval.end),
99            };
100
101        // Process intervals that start within or touch the insertion range
102        while let Some((&next_start, &next_end)) = self.intervals.range(start..=insert_end).next() {
103            assert!(start < next_start);
104            assert!(next_start <= insert_end);
105
106            acc = f(acc, InsertItem::New(start..next_start));
107
108            self.intervals.remove(&next_start);
109
110            if insert_end <= next_end {
111                // The next interval extends beyond or matches insert_end
112                acc = f(acc, InsertItem::Overlap(next_start..insert_end));
113                self.intervals
114                    .insert(insert_start, insert_end.max(next_end));
115                return acc;
116            }
117
118            // The next interval is completely within insert range
119            acc = f(acc, InsertItem::Overlap(next_start..next_end));
120            start = next_end;
121        }
122
123        if start < insert_end {
124            acc = f(acc, InsertItem::New(start..insert_end));
125        }
126        self.intervals.insert(insert_start, insert_end);
127        acc
128    }
129
130    /// 区間を削除する
131    ///
132    /// 初期値 `init`, 関数 `f` による畳み込み結果を返す
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// use disjoint_intervals::{DisjointIntervals, RemoveItem};
138    ///
139    /// let mut intervals = DisjointIntervals::<i32>::new();
140    /// intervals.insert(-10..5, (), |_, _| ());
141    /// let removed = intervals.remove(-5..10, 0, |acc, item| {
142    ///     if let RemoveItem::Remove(item) = item {
143    ///        acc + (item.end - item.start)
144    ///     } else {
145    ///        acc
146    ///     }
147    /// });
148    /// assert_eq!(removed, 10);
149    ///
150    /// assert_eq!(intervals.iter().collect::<Vec<_>>(), vec![-10..-5]);
151    /// ```
152    pub fn remove<U, F>(&mut self, interval: Range<T>, init: U, f: F) -> U
153    where
154        F: FnMut(U, RemoveItem<T>) -> U,
155    {
156        assert!(!interval.is_empty());
157
158        let mut acc = init;
159        let mut f = f;
160        let remove_end = interval.end;
161        let mut start = match self.intervals.range(..=interval.start).last() {
162            Some((&prev_start, &prev_end)) if interval.start < prev_end => {
163                self.intervals.remove(&prev_start);
164
165                if prev_start < interval.start {
166                    self.intervals.insert(prev_start, interval.start);
167                }
168
169                let overlap_end = prev_end.min(remove_end);
170                acc = f(acc, RemoveItem::Remove(interval.start..overlap_end));
171
172                if prev_end > remove_end {
173                    self.intervals.insert(remove_end, prev_end);
174                    return acc;
175                }
176                overlap_end
177            }
178            _ => interval.start,
179        };
180
181        // Process intervals that start within the removal range
182        while let Some((&next_start, &next_end)) = self.intervals.range(start..remove_end).next() {
183            assert!(start <= next_start);
184            assert!(next_start < remove_end);
185
186            if start < next_start {
187                acc = f(acc, RemoveItem::Absent(start..next_start));
188            }
189
190            self.intervals.remove(&next_start);
191
192            if next_end <= remove_end {
193                // The entire interval is removed
194                acc = f(acc, RemoveItem::Remove(next_start..next_end));
195                start = next_end;
196            } else {
197                // The next interval extends beyond remove_end
198                acc = f(acc, RemoveItem::Remove(next_start..remove_end));
199                self.intervals.insert(remove_end, next_end);
200                return acc;
201            }
202        }
203
204        if start < remove_end {
205            acc = f(acc, RemoveItem::Absent(start..remove_end));
206        }
207
208        acc
209    }
210
211    /// `x` 以上の開始点を持つ最初の区間を返す
212    ///
213    /// # Examples
214    ///
215    /// ```
216    /// use disjoint_intervals::DisjointIntervals;
217    ///
218    /// let mut intervals = DisjointIntervals::<i32>::new();
219    /// intervals.insert(0..5, (), |_, _| ());
220    /// intervals.insert(10..15, (), |_, _| ());
221    ///
222    /// assert_eq!(intervals.ge(0), Some(0..5));
223    /// assert_eq!(intervals.ge(3), Some(10..15));
224    /// assert_eq!(intervals.ge(15), None);
225    /// ```
226    pub fn ge(&self, x: T) -> Option<Range<T>> {
227        self.intervals
228            .range(x..)
229            .next()
230            .map(|(&start, &end)| start..end)
231    }
232
233    /// `x` 以下の開始点を持つ最後の区間を返す
234    ///
235    /// # Examples
236    ///
237    /// ```
238    /// use disjoint_intervals::DisjointIntervals;
239    ///
240    /// let mut intervals = DisjointIntervals::<i32>::new();
241    /// intervals.insert(0..5, (), |_, _| ());
242    /// intervals.insert(10..15, (), |_, _| ());
243    ///
244    /// assert_eq!(intervals.le(12), Some(10..15));
245    /// assert_eq!(intervals.le(10), Some(10..15));
246    /// assert_eq!(intervals.le(5), Some(0..5));
247    /// assert_eq!(intervals.le(-1), None);
248    /// ```
249    pub fn le(&self, x: T) -> Option<Range<T>> {
250        self.intervals
251            .range(..=x)
252            .last()
253            .map(|(&start, &end)| start..end)
254    }
255}
256
257impl<T> Debug for DisjointIntervals<T>
258where
259    T: Debug,
260{
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        f.debug_list().entries(self.intervals.iter()).finish()
263    }
264}
265
266impl<T> Default for DisjointIntervals<T>
267where
268    T: Ord + Clone + Copy,
269{
270    fn default() -> Self {
271        Self::new()
272    }
273}
274
275#[cfg(test)]
276mod tests {
277    use crate::{DisjointIntervals, InsertItem, RemoveItem};
278
279    #[test]
280    fn test_insert_disjoint() {
281        let mut intervals = DisjointIntervals::<i32>::new();
282        intervals.insert(-10..5, (), |_, _| ());
283        intervals.insert(10..15, (), |_, _| ());
284
285        let mut it = intervals.iter();
286        assert_eq!(it.next(), Some(-10..5));
287        assert_eq!(it.next(), Some(10..15));
288        assert_eq!(it.next(), None);
289    }
290
291    #[test]
292    fn test_insert_subset() {
293        let mut intervals = DisjointIntervals::<i32>::new();
294        intervals.insert(-10..5, (), |_, _| ());
295        intervals.insert(-5..0, (), |_, _| ());
296
297        let mut it = intervals.iter();
298        assert_eq!(it.next(), Some(-10..5));
299        assert_eq!(it.next(), None);
300    }
301
302    #[test]
303    fn test_insert_superset() {
304        let mut intervals = DisjointIntervals::<i32>::new();
305        intervals.insert(-5..0, (), |_, _| ());
306        intervals.insert(-10..5, (), |_, _| ());
307
308        let mut it = intervals.iter();
309        assert_eq!(it.next(), Some(-10..5));
310        assert_eq!(it.next(), None);
311    }
312
313    #[test]
314    fn test_insert_intersect() {
315        let mut intervals = DisjointIntervals::<i32>::new();
316        intervals.insert(-10..5, (), |_, _| ());
317        intervals.insert(0..10, (), |_, _| ());
318
319        let mut it = intervals.iter();
320        assert_eq!(it.next(), Some(-10..10));
321        assert_eq!(it.next(), None);
322    }
323
324    #[test]
325    fn test_insert_intersect_3() {
326        let mut intervals = DisjointIntervals::<i32>::new();
327        intervals.insert(-10..5, (), |_, _| ());
328        intervals.insert(10..20, (), |_, _| ());
329        intervals.insert(0..12, (), |_, _| ());
330
331        let mut it = intervals.iter();
332        assert_eq!(it.next(), Some(-10..20));
333        assert_eq!(it.next(), None);
334    }
335
336    #[test]
337    fn test_insert_touch_left_right() {
338        let mut intervals = DisjointIntervals::<i32>::new();
339        intervals.insert(-10..5, (), |_, _| ());
340        intervals.insert(5..10, (), |_, _| ());
341
342        let mut it = intervals.iter();
343        assert_eq!(it.next(), Some(-10..10));
344        assert_eq!(it.next(), None);
345    }
346
347    #[test]
348    fn test_insert_touch_right_left() {
349        let mut intervals = DisjointIntervals::<i32>::new();
350        intervals.insert(5..10, (), |_, _| ());
351        intervals.insert(-10..5, (), |_, _| ());
352
353        let mut it = intervals.iter();
354        assert_eq!(it.next(), Some(-10..10));
355        assert_eq!(it.next(), None);
356    }
357
358    #[test]
359    fn test_insert_touch_3() {
360        let mut intervals = DisjointIntervals::<i32>::new();
361        intervals.insert(-10..5, (), |_, _| ());
362        intervals.insert(10..20, (), |_, _| ());
363        intervals.insert(5..10, (), |_, _| ());
364
365        let mut it = intervals.iter();
366        assert_eq!(it.next(), Some(-10..20));
367        assert_eq!(it.next(), None);
368    }
369
370    #[test]
371    fn test_insert_fold_1() {
372        let mut intervals = DisjointIntervals::<i32>::new();
373
374        let insert_items = intervals.insert(-10..5, Vec::new(), |mut acc, item| {
375            acc.push(item);
376            acc
377        });
378        assert_eq!(insert_items, vec![InsertItem::New(-10..5)]);
379    }
380
381    #[test]
382    fn test_insert_fold() {
383        let mut intervals = DisjointIntervals::<i32>::new();
384        intervals.insert(-10..-5, (), |_, _| ());
385        intervals.insert(0..5, (), |_, _| ());
386        intervals.insert(10..15, (), |_, _| ());
387
388        let insert_items = intervals.insert(-7..12, Vec::new(), |mut acc, item| {
389            acc.push(item);
390            acc
391        });
392        assert_eq!(
393            insert_items,
394            vec![
395                InsertItem::Overlap(-7..-5),
396                InsertItem::New(-5..0),
397                InsertItem::Overlap(0..5),
398                InsertItem::New(5..10),
399                InsertItem::Overlap(10..12)
400            ],
401        );
402    }
403
404    #[test]
405    fn test_remove_subset() {
406        let mut intervals = DisjointIntervals::<i32>::new();
407        intervals.insert(-10..5, (), |_, _| ());
408        intervals.remove(-5..0, (), |_, _| ());
409
410        let mut it = intervals.iter();
411        assert_eq!(it.next(), Some(-10..-5));
412        assert_eq!(it.next(), Some(0..5));
413        assert_eq!(it.next(), None);
414    }
415
416    #[test]
417    fn test_remove_superset() {
418        let mut intervals = DisjointIntervals::<i32>::new();
419        intervals.insert(-5..0, (), |_, _| ());
420        intervals.remove(-10..5, (), |_, _| ());
421
422        let mut it = intervals.iter();
423        assert_eq!(it.next(), None);
424    }
425
426    #[test]
427    fn test_remove_intersect() {
428        let mut intervals = DisjointIntervals::<i32>::new();
429        intervals.insert(-10..5, (), |_, _| ());
430        intervals.remove(0..10, (), |_, _| ());
431
432        let mut it = intervals.iter();
433        assert_eq!(it.next(), Some(-10..0));
434        assert_eq!(it.next(), None);
435    }
436
437    #[test]
438    fn test_remove_touch_left() {
439        let mut intervals = DisjointIntervals::<i32>::new();
440        intervals.insert(-10..5, (), |_, _| ());
441        intervals.remove(-10..0, (), |_, _| ());
442
443        let mut it = intervals.iter();
444        assert_eq!(it.next(), Some(0..5));
445        assert_eq!(it.next(), None);
446    }
447
448    #[test]
449    fn test_remove_touch_right() {
450        let mut intervals = DisjointIntervals::<i32>::new();
451        intervals.insert(5..10, (), |_, _| ());
452        intervals.remove(8..10, (), |_, _| ());
453
454        let mut it = intervals.iter();
455        assert_eq!(it.next(), Some(5..8));
456        assert_eq!(it.next(), None);
457    }
458
459    #[test]
460    fn test_remove_exact() {
461        let mut intervals = DisjointIntervals::<i32>::new();
462        intervals.insert(-10..5, (), |_, _| ());
463        intervals.remove(-10..5, (), |_, _| ());
464
465        let mut it = intervals.iter();
466        assert_eq!(it.next(), None);
467    }
468
469    #[test]
470    fn test_remove_fold_empty() {
471        let mut intervals = DisjointIntervals::<i32>::new();
472
473        let remove_items = intervals.remove(-10..5, Vec::new(), |mut acc, item| {
474            acc.push(item);
475            acc
476        });
477
478        assert_eq!(remove_items, vec![RemoveItem::Absent(-10..5)]);
479    }
480
481    #[test]
482    fn test_remove_fold() {
483        use crate::RemoveItem;
484
485        let mut intervals = DisjointIntervals::<i32>::new();
486        intervals.insert(-10..-5, (), |_, _| ());
487        intervals.insert(0..5, (), |_, _| ());
488        intervals.insert(10..15, (), |_, _| ());
489
490        let remove_items = intervals.remove(-7..12, Vec::new(), |mut acc, item| {
491            acc.push(item);
492            acc
493        });
494        assert_eq!(
495            remove_items,
496            vec![
497                RemoveItem::Remove(-7..-5),
498                RemoveItem::Absent(-5..0),
499                RemoveItem::Remove(0..5),
500                RemoveItem::Absent(5..10),
501                RemoveItem::Remove(10..12)
502            ],
503        );
504
505        let mut it = intervals.iter();
506        assert_eq!(it.next(), Some(-10..-7));
507        assert_eq!(it.next(), Some(12..15));
508        assert_eq!(it.next(), None);
509    }
510}