snippets 0.1.0
Loading...
Searching...
No Matches
interval.hpp
Go to the documentation of this file.
1#ifndef INTERVAL_H
2#define INTERVAL_H
3
4#include <map>
5#include <concepts>
6#include <optional>
7#include <cassert>
8#include <set>
9
10namespace hsc_snippets {
11 template<std::integral T>
12 struct Interval {
13 T left; // inclusive
14 T right; // exclusive
15 };
16
17 /*
18 * transparent comparison:
19 *
20 * 2 is no less than [1,3]
21 * [1,3] is no less than 2
22 * So 2 is equivalent to [1,3]
23 *
24 * 1 is no less than [1,3]
25 * [1,3] is no less than 1
26 * So 1 is equivalent to [1,3]
27 *
28 * 3 is no less than [1,3]
29 * [1,3] is less than 3
30 * So 3 is not equivalent to [1,3]
31 *
32 */
33 template<std::integral T>
34 static bool operator<(const Interval<T> &interval, T x) {
35 return interval.right <= x;
36 }
37
38 template<std::integral T>
39 static bool operator<(T x, const Interval<T> &interval) {
40 return x < interval.left;
41 }
42
43 // we ensure that intervals never overlap
44 template<std::integral T>
45 static bool operator<(const Interval<T> &interval1, const Interval<T> &interval2) {
46 return interval1.left < interval2.left;
47 }
48
49 template<std::integral T>
50 struct Override {
51 T operator()(T old_value, T new_value) const {
52 return new_value;
53 }
54 };
55
56 template<std::integral T>
57 struct Maximum {
58 T operator()(T old_value, T new_value) const {
59 return std::max(old_value, new_value);
60 }
61 };
62
75 template<std::integral T, std::integral V, typename update_policy_t = Override<T> >
76 // update_policy_t is a callable with a signature of V(V old_value, V new_value)
78 public:
79 explicit IntervalMap() = default;
80
89 void update(T left, T right, V value) {
90 assert(left < right); // or UB
91
92 auto it = map.find(left);
93 if (it != map.end()) {
94 auto p = *it;
95 map.erase(it);
96
97 // the value for the overlapped area
98 auto _value = update_policy(p.second, value);
99
100 // the code below is messy in effort to eliminate fragmentation
101
102 if (p.first.right > right) {
103 // [p.first.left, left) p.second
104 // [left, right) _value
105 // [right, p.first.right) p.second
106
107 if (_value != p.second) {
108 if (p.first.left != left) {
109 map.insert({Interval<T>{p.first.left, left}, p.second});
110 }
111 map.insert({Interval<T>{left, right}, _value});
112 map.insert({Interval<T>{right, p.first.right}, p.second});
113 } else {
114 map.insert({Interval<T>{p.first.left, p.first.right}, _value});
115 }
116 } else {
117 // [p.first.left, left) p.second
118 // [left, p.first.right) _value
119 // [p.first.right, right) We don't know!!!
120
121 if (_value != p.second) {
122 if (p.first.left != left) {
123 map.insert({Interval<T>{p.first.left, left}, p.second});
124 }
125 map.insert({Interval<T>{left, p.first.right}, _value});
126 } else {
127 map.insert({Interval<T>{p.first.left, p.first.right}, _value});
128 }
129
130 if (p.first.right != right) {
131 // this is non-trivial
132 update(p.first.right, right, value);
133
134 // here there might be a fragmentation
135 }
136 }
137
138 return;
139 }
140
141 if (right - 1 > right) {
142 throw std::overflow_error("right underflows.");
143 }
144 it = map.find(right - 1);
145
146 if (it != map.end()) {
147 auto p = *it;
148 map.erase(it);
149 assert(left < p.first.left); // or map.find(left)!=map.end(), we should not in this branch
150 assert(right > p.first.left);
151 assert(right <= p.first.right);
152
153 update(left, p.first.left, value);
154
155 auto _value = update_policy(p.second, value);
156
157 // [p.first.left, right) _value
158 // [right, p.first.right) p.second
159
160 if (_value == p.second) {
161 map.insert({Interval<T>{p.first.left, p.first.right}, _value});
162 } else {
163 map.insert({Interval<T>{p.first.left, right}, _value});
164 if (right < p.first.right) {
165 map.insert({Interval<T>{right, p.first.right}, p.second});
166 }
167 }
168
169 return;
170 }
171
172 // the first element that is no less than left
173 // or interval.end>left
174 it = map.lower_bound(left);
175 if (it == map.end()) {
176 // here there might be a fragmentation
177 map.insert({Interval<T>{left, right}, value});
178 } else {
179 auto p = *it;
180 assert(left < p.first.left);
181
182 // we can safely add a new interval here.
183 if (right <= p.first.left) {
184 map.insert({Interval<T>{left, right}, value});
185 } else {
186 map.erase(it);
187 // if not, we add [left,p.first.left)
188 map.insert({Interval<T>{left, p.first.left}, value});
189 // and update [p.first.left,end)
190 update(p.first.left, right, value);
191 }
192 }
193 }
194
201 std::optional<V> query(T index) {
202 auto it = map.find(index);
203 if (it == map.end()) {
204 return std::nullopt;
205 } else {
206 return it->second;
207 }
208 }
209
213 void defragment() {
214 // We assume that erasion only affects the iterator of the erased element.
215 if (map.size() < 2) {
216 return;
217 }
218 auto it = map.begin();
219 auto right = it->first.right;
220 auto value = it->second;
221 auto next_it = std::next(it);
222
223 do {
224 if (right == next_it->first.left && value == next_it->second) {
225 auto new_left = it->first.left;
226 auto new_right = next_it->first.right;
227 map.erase(next_it);
228 map.erase(it);
229 auto [new_it, success] = map.insert({Interval<T>{new_left, new_right}, value});
230 assert(success);
231 it = new_it;
232
233 right = it->first.right;
234 value = it->second;
235 next_it = std::next(it);
236 } else {
237 it = std::next(it);
238 right = it->first.right;
239 value = it->second;
240 next_it = std::next(it);
241 }
242 } while (next_it != map.end());
243
244 assert(no_fragmentation());
245 }
246
253 std::vector<std::tuple<T, T, V> > getIntervals() const {
254 std::vector<std::tuple<T, T, V> > intervals;
255 intervals.reserve(map.size());
256
257 for (const auto &entry: map) {
258 intervals.emplace_back(entry.first.left, entry.first.right, entry.second);
259 }
260
261 return intervals;
262 }
263
264 private:
270 bool no_fragmentation() {
271 if (map.empty()) {
272 return true;
273 }
274
275 auto it = map.begin();
276 auto right = it->first.right;
277 auto value = it->second;
278
279 it = std::next(it);
280 for (; it != map.end(); it = std::next(it)) {
281 if (right == it->first.left && value == it->second) {
282 return false;
283 }
284
285 right = it->first.right;
286 value = it->second;
287 }
288 return true;
289 }
290
291 std::map<Interval<T>, V, std::less<> > map;
292 update_policy_t update_policy;
293 };
294
295
296 template<std::integral T>
298 public:
299 explicit IntervalSet() = default;
300
308 void update(T left, T right) {
309 assert(left < right); // or UB
310
311 auto it = s.find(left);
312 if (it != s.end()) {
313 Interval<T> interval = *it;
314 s.erase(it);
315
316
317 // the code below is messy in effort to eliminate fragmentation
318
319 if (interval.right > right) {
320 // [interval.left, left)
321 // [left, right)
322 // [right, interval.right)
323
324 s.insert(Interval<T>{interval.left, interval.right});
325 } else {
326 // [interval.left, left)
327 // [left, interval.right)
328 // [interval.right, right)
329
330
331 s.insert(Interval<T>{interval.left, interval.right});
332
333
334 if (interval.right != right) {
336 update(interval.right, right);
337
338 // here there might be a fragmentation
339 }
340 }
341
342 return;
343 }
344
345 if (right - 1 > right) {
346 throw std::overflow_error("right underflows.");
347 }
348 it = s.find(right - 1);
349
350 if (it != s.end()) {
351 Interval<T> interval = *it;
352 s.erase(it);
353 assert(left < interval.left); // or s.find(left)!=s.end(), we should not in this branch
354 assert(right > interval.left);
355 assert(right <= interval.right);
356
357 update(left, interval.left);
358
359 // [interval.left, right)
360 // [right, interval.right)
361
362 s.insert(Interval<T>{interval.left, interval.right});
363
364 return;
365 }
366
367 // the first element that is no less than left
368 // or interval.end>left
369 it = s.lower_bound(left);
370 if (it == s.end()) {
371 // here there might be a fragmentation
372 s.insert(Interval<T>{left, right});
373 } else {
374 Interval<T> interval = *it;
375 assert(left < interval.left);
376
377 // we can safely add a new interval here.
378 if (right <= interval.left) {
379 s.insert(Interval<T>{left, right});
380 } else {
381 s.erase(it);
382 // if not, we add [left,interval.left)
383 s.insert(Interval<T>{left, interval.left});
384 // and update [interval.left,end)
385 update(interval.left, right);
386 }
387 }
388 }
389
396 bool query(T index) const {
397 auto it = s.find(index);
398 return it != s.end();
399 }
400
407 bool query(const Interval<T> &interval) const {
408 assert(interval.left < interval.right); // The interval must be valid
409
410 // Find the first interval in the set that is not less than the query interval
411 auto it = s.lower_bound(interval);
412
413 // Check if the previous interval overlaps with the query interval
414 if (it != s.begin()) {
415 auto prev_it = std::prev(it);
416 if (prev_it->right > interval.left) {
417 // There is an overlap with the previous interval
418 return true;
419 }
420 }
421
422 // Check if the current interval overlaps with the query interval
423 if (it != s.end() && it->left < interval.right) {
424 // There is an overlap with the current interval
425 return true;
426 }
427
428 // No overlapping intervals found
429 return false;
430 }
431
437 std::vector<std::pair<T, T> > getIntervals() const {
438 std::vector<std::pair<T, T> > intervals;
439 intervals.reserve(s.size());
440
441 for (const auto &interval: s) {
442 intervals.emplace_back(interval.left, interval.right);
443 }
444
445 return intervals;
446 }
447
448
452 void defragment() {
453 // We assume that erasion only affects the iterator of the erased element.
454 if (s.size() < 2) {
455 return;
456 }
457 auto it = s.begin();
458 auto right = it->right;
459 auto next_it = std::next(it);
460
461 do {
462 if (right == next_it->left) {
463 auto new_left = it->left;
464 auto new_right = next_it->right;
465 s.erase(next_it);
466 s.erase(it);
467 auto [new_it, success] = s.insert(Interval<T>{new_left, new_right});
468 assert(success);
469 it = new_it;
470
471 right = it->right;
472 next_it = std::next(it);
473 } else {
474 it = std::next(it);
475 right = it->right;
476 next_it = std::next(it);
477 }
478 } while (next_it != s.end());
479
480 assert(no_fragmentation());
481 }
482
483 private:
489 bool no_fragmentation() {
490 if (s.empty()) {
491 return true;
492 }
493
494 auto it = s.begin();
495 auto right = it->right;
496
497 it = std::next(it);
498 for (; it != s.end(); it = std::next(it)) {
499 if (right == it->left) {
500 return false;
501 }
502 right = it->right;
503 }
504 return true;
505 }
506
507 std::set<Interval<T>, std::less<> > s;
508 };
509}
510
511#endif // INTERVAL_H
Definition interval.hpp:77
std::vector< std::tuple< T, T, V > > getIntervals() const
Definition interval.hpp:253
std::optional< V > query(T index)
Definition interval.hpp:201
void defragment()
Definition interval.hpp:213
void update(T left, T right, V value)
Definition interval.hpp:89
Definition interval.hpp:297
void defragment()
Definition interval.hpp:452
void update(T left, T right)
Definition interval.hpp:308
bool query(const Interval< T > &interval) const
Definition interval.hpp:407
std::vector< std::pair< T, T > > getIntervals() const
Definition interval.hpp:437
bool query(T index) const
Definition interval.hpp:396
Definition big_integer.hpp:14
static bool operator<(const Interval< T > &interval, T x)
Definition interval.hpp:34
Definition interval.hpp:12
T left
Definition interval.hpp:13
T right
Definition interval.hpp:14
Definition interval.hpp:57
T operator()(T old_value, T new_value) const
Definition interval.hpp:58
Definition interval.hpp:50
T operator()(T old_value, T new_value) const
Definition interval.hpp:51