Skip to content

Commit cf39f3a

Browse files
committed
patch: merge points over inserting them
When points can merge together eg [1,5] [6,9] -> [1,9] we transform the value at the insertion point.
1 parent 4ee9add commit cf39f3a

File tree

3 files changed

+153
-3
lines changed

3 files changed

+153
-3
lines changed

include/ctre/first.hpp

+51-1
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,64 @@ template <size_t Capacity> class point_set {
434434
obj = tmp;
435435
//std::swap(*it, obj);
436436

437+
used++;
438+
return out;
439+
}
440+
}
441+
constexpr bool can_merge(point lhs, point rhs) noexcept {
442+
point expanded_lhs = lhs;
443+
//expand ranges by 1 in each direction
444+
expanded_lhs.low -= (expanded_lhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
445+
expanded_lhs.high += (expanded_lhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
446+
447+
point expanded_rhs = rhs;
448+
expanded_rhs.low -= (expanded_rhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
449+
expanded_rhs.high += (expanded_rhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
450+
//for example [1,5] and [6,9] can merge into [1,9]
451+
return (expanded_lhs.low <= rhs.high && rhs.low <= expanded_lhs.high) ||
452+
(expanded_rhs.low <= lhs.high && lhs.low <= expanded_rhs.high);
453+
}
454+
constexpr point* insert_or_merge_point(int64_t position, int64_t other) {
455+
point obj{ position, other };
456+
auto it = lower_bound(obj);
457+
if (it == end()) {
458+
if (used && can_merge(*(it-1), obj)) {
459+
auto back = it - 1;
460+
back->low = back->low < obj.low ? back->low : obj.low;
461+
back->high = back->high > obj.high ? back->high : obj.high;
462+
} else {
463+
*it = obj;
464+
used++;
465+
}
466+
return it;
467+
} else {
468+
auto out = it;
469+
//good chance we can merge here
470+
if (can_merge(*it, obj)) {
471+
//merge the points together vs inserting
472+
it->low = it->low < obj.low ? it->low : obj.low;
473+
it->high = it->high > obj.high ? it->high : obj.high;
474+
return out;
475+
}
476+
auto e = end();
477+
while (it != e) {
478+
auto tmp = *it;
479+
*it = obj;
480+
obj = tmp;
481+
it++;
482+
}
483+
auto tmp = *it;
484+
*it = obj;
485+
obj = tmp;
486+
437487
used++;
438488
return out;
439489
}
440490
}
441491
public:
442492
constexpr point_set() { }
443493
constexpr void insert(int64_t low, int64_t high) {
444-
insert_point(low, high);
494+
insert_or_merge_point(low, high);
445495
//insert_point(high, low);
446496
}
447497
constexpr bool check(int64_t low, int64_t high) {

single-header/ctre-unicode.hpp

+51-1
Original file line numberDiff line numberDiff line change
@@ -3872,14 +3872,64 @@ template <size_t Capacity> class point_set {
38723872
obj = tmp;
38733873
//std::swap(*it, obj);
38743874

3875+
used++;
3876+
return out;
3877+
}
3878+
}
3879+
constexpr bool can_merge(point lhs, point rhs) noexcept {
3880+
point expanded_lhs = lhs;
3881+
//expand ranges by 1 in each direction
3882+
expanded_lhs.low -= (expanded_lhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
3883+
expanded_lhs.high += (expanded_lhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
3884+
3885+
point expanded_rhs = rhs;
3886+
expanded_rhs.low -= (expanded_rhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
3887+
expanded_rhs.high += (expanded_rhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
3888+
//for example [1,5] and [6,9] can merge into [1,9]
3889+
return (expanded_lhs.low <= rhs.high && rhs.low <= expanded_lhs.high) ||
3890+
(expanded_rhs.low <= lhs.high && lhs.low <= expanded_rhs.high);
3891+
}
3892+
constexpr point* insert_or_merge_point(int64_t position, int64_t other) {
3893+
point obj{ position, other };
3894+
auto it = lower_bound(obj);
3895+
if (it == end()) {
3896+
if (used && can_merge(*(it-1), obj)) {
3897+
auto back = it - 1;
3898+
back->low = back->low < obj.low ? back->low : obj.low;
3899+
back->high = back->high > obj.high ? back->high : obj.high;
3900+
} else {
3901+
*it = obj;
3902+
used++;
3903+
}
3904+
return it;
3905+
} else {
3906+
auto out = it;
3907+
//good chance we can merge here
3908+
if (can_merge(*it, obj)) {
3909+
//merge the points together vs inserting
3910+
it->low = it->low < obj.low ? it->low : obj.low;
3911+
it->high = it->high > obj.high ? it->high : obj.high;
3912+
return out;
3913+
}
3914+
auto e = end();
3915+
while (it != e) {
3916+
auto tmp = *it;
3917+
*it = obj;
3918+
obj = tmp;
3919+
it++;
3920+
}
3921+
auto tmp = *it;
3922+
*it = obj;
3923+
obj = tmp;
3924+
38753925
used++;
38763926
return out;
38773927
}
38783928
}
38793929
public:
38803930
constexpr point_set() { }
38813931
constexpr void insert(int64_t low, int64_t high) {
3882-
insert_point(low, high);
3932+
insert_or_merge_point(low, high);
38833933
//insert_point(high, low);
38843934
}
38853935
constexpr bool check(int64_t low, int64_t high) {

single-header/ctre.hpp

+51-1
Original file line numberDiff line numberDiff line change
@@ -3869,14 +3869,64 @@ template <size_t Capacity> class point_set {
38693869
obj = tmp;
38703870
//std::swap(*it, obj);
38713871

3872+
used++;
3873+
return out;
3874+
}
3875+
}
3876+
constexpr bool can_merge(point lhs, point rhs) noexcept {
3877+
point expanded_lhs = lhs;
3878+
//expand ranges by 1 in each direction
3879+
expanded_lhs.low -= (expanded_lhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
3880+
expanded_lhs.high += (expanded_lhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
3881+
3882+
point expanded_rhs = rhs;
3883+
expanded_rhs.low -= (expanded_rhs.low > std::numeric_limits<int64_t>::min()) ? 1 : 0;
3884+
expanded_rhs.high += (expanded_rhs.high < std::numeric_limits<int64_t>::max()) ? 1 : 0;
3885+
//for example [1,5] and [6,9] can merge into [1,9]
3886+
return (expanded_lhs.low <= rhs.high && rhs.low <= expanded_lhs.high) ||
3887+
(expanded_rhs.low <= lhs.high && lhs.low <= expanded_rhs.high);
3888+
}
3889+
constexpr point* insert_or_merge_point(int64_t position, int64_t other) {
3890+
point obj{ position, other };
3891+
auto it = lower_bound(obj);
3892+
if (it == end()) {
3893+
if (used && can_merge(*(it-1), obj)) {
3894+
auto back = it - 1;
3895+
back->low = back->low < obj.low ? back->low : obj.low;
3896+
back->high = back->high > obj.high ? back->high : obj.high;
3897+
} else {
3898+
*it = obj;
3899+
used++;
3900+
}
3901+
return it;
3902+
} else {
3903+
auto out = it;
3904+
//good chance we can merge here
3905+
if (can_merge(*it, obj)) {
3906+
//merge the points together vs inserting
3907+
it->low = it->low < obj.low ? it->low : obj.low;
3908+
it->high = it->high > obj.high ? it->high : obj.high;
3909+
return out;
3910+
}
3911+
auto e = end();
3912+
while (it != e) {
3913+
auto tmp = *it;
3914+
*it = obj;
3915+
obj = tmp;
3916+
it++;
3917+
}
3918+
auto tmp = *it;
3919+
*it = obj;
3920+
obj = tmp;
3921+
38723922
used++;
38733923
return out;
38743924
}
38753925
}
38763926
public:
38773927
constexpr point_set() { }
38783928
constexpr void insert(int64_t low, int64_t high) {
3879-
insert_point(low, high);
3929+
insert_or_merge_point(low, high);
38803930
//insert_point(high, low);
38813931
}
38823932
constexpr bool check(int64_t low, int64_t high) {

0 commit comments

Comments
 (0)