2015-04-18 01:35:36 +00:00
|
|
|
/* Algorithms for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_ALGORITHM_H
|
|
|
|
#define OCTA_ALGORITHM_H
|
|
|
|
|
2015-04-20 18:06:47 +00:00
|
|
|
#include <math.h>
|
2015-04-18 22:12:45 +00:00
|
|
|
|
2015-04-18 01:35:36 +00:00
|
|
|
#include "octa/functional.h"
|
2015-04-18 19:20:40 +00:00
|
|
|
#include "octa/range.h"
|
2015-04-20 01:14:55 +00:00
|
|
|
#include "octa/utility.h"
|
2015-04-20 18:06:47 +00:00
|
|
|
#include "octa/initializer_list.h"
|
2015-04-18 01:35:36 +00:00
|
|
|
|
|
|
|
namespace octa {
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* partitioning */
|
|
|
|
|
2015-04-18 20:46:31 +00:00
|
|
|
template<typename R, typename U>
|
|
|
|
R partition(R range, U pred) {
|
|
|
|
R ret = range;
|
|
|
|
for (; !range.empty(); range.pop_first()) {
|
|
|
|
if (pred(range.first())) {
|
|
|
|
swap(range.first(), ret.first());
|
|
|
|
ret.pop_first();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-20 01:06:42 +00:00
|
|
|
template<typename R, typename P>
|
|
|
|
bool is_partitioned(R range, P pred) {
|
|
|
|
for (; !range.empty() && pred(range.first()); range.pop_first());
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (pred(range.first())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-05-24 17:22:35 +00:00
|
|
|
/* sorting */
|
2015-04-24 17:16:35 +00:00
|
|
|
|
2015-04-18 19:20:40 +00:00
|
|
|
template<typename R, typename C>
|
2015-05-24 17:22:35 +00:00
|
|
|
void __octa_insort(R range, C compare) {
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> rlen = range.length();
|
|
|
|
for (RangeSize<R> i = 1; i < rlen; ++i) {
|
2015-05-24 17:22:35 +00:00
|
|
|
RangeSize<R> j = i;
|
|
|
|
RangeReference<R> v = range[i];
|
2015-04-18 19:20:40 +00:00
|
|
|
while (j > 0 && !compare(range[j - 1], v)) {
|
|
|
|
range[j] = range[j - 1];
|
|
|
|
--j;
|
|
|
|
}
|
|
|
|
range[j] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaUnaryCompare {
|
|
|
|
const T &val;
|
|
|
|
U comp;
|
|
|
|
bool operator()(const T &v) const { return comp(v, val); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename R, typename C>
|
2015-05-03 20:54:26 +00:00
|
|
|
void __octa_hs_sift_down(R range, RangeSize<R> s,
|
|
|
|
RangeSize<R> e, C compare) {
|
|
|
|
RangeSize<R> r = s;
|
2015-04-24 17:16:35 +00:00
|
|
|
while ((r * 2 + 1) <= e) {
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> ch = r * 2 + 1;
|
|
|
|
RangeSize<R> sw = r;
|
2015-04-24 17:16:35 +00:00
|
|
|
if (compare(range[sw], range[ch]))
|
|
|
|
sw = ch;
|
|
|
|
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
|
|
|
sw = ch + 1;
|
|
|
|
if (sw != r) {
|
|
|
|
swap(range[r], range[sw]);
|
|
|
|
r = sw;
|
|
|
|
} else return;
|
2015-04-18 22:12:45 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-18 22:12:45 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
template<typename R, typename C>
|
|
|
|
void __octa_heapsort(R range, C compare) {
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> len = range.length();
|
|
|
|
RangeSize<R> st = (len - 2) / 2;
|
2015-04-24 17:16:35 +00:00
|
|
|
for (;;) {
|
|
|
|
__octa_hs_sift_down(range, st, len - 1, compare);
|
|
|
|
if (st-- == 0) break;
|
|
|
|
}
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> e = len - 1;
|
2015-04-24 17:16:35 +00:00
|
|
|
while (e > 0) {
|
|
|
|
swap(range[e], range[0]);
|
|
|
|
--e;
|
|
|
|
__octa_hs_sift_down(range, 0, e, compare);
|
2015-04-18 22:12:45 +00:00
|
|
|
}
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-04-18 22:12:45 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
template<typename R, typename C>
|
2015-05-03 20:54:26 +00:00
|
|
|
void __octa_introloop(R range, C compare, RangeSize<R> depth) {
|
2015-04-24 17:16:35 +00:00
|
|
|
if (range.length() <= 10) {
|
2015-05-24 17:22:35 +00:00
|
|
|
__octa_insort(range, compare);
|
2015-04-24 17:16:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (depth == 0) {
|
|
|
|
__octa_heapsort(range, compare);
|
|
|
|
return;
|
2015-04-18 21:33:19 +00:00
|
|
|
}
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeReference<R> p = range[range.length() / 2];
|
2015-04-24 17:16:35 +00:00
|
|
|
swap(p, range.last());
|
|
|
|
R r = partition(range, __OctaUnaryCompare<decltype(p), C>{ p, compare });
|
|
|
|
R l = range.slice(0, range.length() - r.length());
|
|
|
|
swap(r.first(), r.last());
|
|
|
|
__octa_introloop(l, compare, depth - 1);
|
|
|
|
__octa_introloop(r, compare, depth - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename C>
|
|
|
|
void __octa_introsort(R range, C compare) {
|
2015-05-03 20:54:26 +00:00
|
|
|
__octa_introloop(range, compare, RangeSize<R>(2
|
2015-04-24 17:16:35 +00:00
|
|
|
* (log(range.length()) / log(2))));
|
2015-04-18 21:33:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-18 19:20:40 +00:00
|
|
|
template<typename R, typename C>
|
|
|
|
void sort(R range, C compare) {
|
2015-04-24 17:16:35 +00:00
|
|
|
__octa_introsort(range, compare);
|
2015-04-18 19:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
void sort(R range) {
|
2015-05-03 20:54:26 +00:00
|
|
|
sort(range, Less<RangeValue<R>>());
|
2015-04-18 19:20:40 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* min/max(_element) */
|
|
|
|
|
2015-04-18 23:02:38 +00:00
|
|
|
template<typename T>
|
|
|
|
inline const T &min(const T &a, const T &b) {
|
|
|
|
return (a < b) ? a : b;
|
|
|
|
}
|
|
|
|
template<typename T, typename C>
|
|
|
|
inline const T &min(const T &a, const T &b, C compare) {
|
|
|
|
return compare(a, b) ? a : b;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline const T &max(const T &a, const T &b) {
|
|
|
|
return (a < b) ? b : a;
|
|
|
|
}
|
|
|
|
template<typename T, typename C>
|
|
|
|
inline const T &max(const T &a, const T &b, C compare) {
|
|
|
|
return compare(a, b) ? b : a;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
inline R min_element(R range) {
|
|
|
|
R r = range;
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (min(r.first(), range.first()) == range.first())
|
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
template<typename R, typename C>
|
|
|
|
inline R min_element(R range, C compare) {
|
|
|
|
R r = range;
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (min(r.first(), range.first(), compare) == range.first())
|
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
inline R max_element(R range) {
|
|
|
|
R r = range;
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (max(r.first(), range.first()) == range.first())
|
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
template<typename R, typename C>
|
|
|
|
inline R max_element(R range, C compare) {
|
|
|
|
R r = range;
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (max(r.first(), range.first(), compare) == range.first())
|
|
|
|
r = range;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T min(InitializerList<T> il) {
|
2015-05-24 01:31:54 +00:00
|
|
|
return min_element(il.each()).first();
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
|
|
|
template<typename T, typename C>
|
|
|
|
inline T min(InitializerList<T> il, C compare) {
|
2015-05-24 01:31:54 +00:00
|
|
|
return min_element(il.each(), compare).first();
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T max(InitializerList<T> il) {
|
2015-05-24 01:31:54 +00:00
|
|
|
return max_element(il.each()).first();
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
2015-04-20 01:21:27 +00:00
|
|
|
|
2015-04-18 23:02:38 +00:00
|
|
|
template<typename T, typename C>
|
|
|
|
inline T max(InitializerList<T> il, C compare) {
|
2015-05-24 01:31:54 +00:00
|
|
|
return max_element(il.each(), compare).first();
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
2015-04-20 01:14:55 +00:00
|
|
|
|
2015-04-26 17:45:10 +00:00
|
|
|
/* clamp */
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
inline T clamp(const T &v, const U &lo, const U &hi) {
|
|
|
|
return max(T(lo), min(v, T(hi)));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U, typename C>
|
|
|
|
inline T clamp(const T &v, const U &lo, const U &hi, C compare) {
|
|
|
|
return max(T(lo), min(v, T(hi), compare), compare);
|
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* algos that don't change the range */
|
|
|
|
|
2015-04-20 01:14:55 +00:00
|
|
|
template<typename R, typename F>
|
|
|
|
F for_each(R range, F func) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
func(range.first());
|
|
|
|
return move(func);
|
|
|
|
}
|
2015-04-20 01:21:27 +00:00
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
bool all_of(R range, P pred) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (!pred(range.first())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
bool any_of(R range, P pred) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (pred(range.first())) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
bool none_of(R range, P pred) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (pred(range.first())) return false;
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-21 01:33:58 +00:00
|
|
|
|
|
|
|
template<typename R, typename T>
|
|
|
|
R find(R range, const T &v) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (range.first() == v)
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
R find_if(R range, P pred) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (pred(range.first()))
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
R find_if_not(R range, P pred) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (!pred(range.first()))
|
|
|
|
break;
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename T>
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> count(R range, const T &v) {
|
|
|
|
RangeSize<R> ret = 0;
|
2015-04-21 01:33:58 +00:00
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (range.first() == v)
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> count_if(R range, P pred) {
|
|
|
|
RangeSize<R> ret = 0;
|
2015-04-21 01:33:58 +00:00
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (pred(range.first()))
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
2015-05-03 20:54:26 +00:00
|
|
|
RangeSize<R> count_if_not(R range, P pred) {
|
|
|
|
RangeSize<R> ret = 0;
|
2015-04-21 01:33:58 +00:00
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
if (!pred(range.first()))
|
|
|
|
++ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R>
|
|
|
|
bool equal(R range1, R range2) {
|
|
|
|
for (; !range1.empty(); range1.pop_first()) {
|
|
|
|
if (range2.empty() || (range1.first() != range2.first()))
|
|
|
|
return false;
|
|
|
|
range2.pop_first();
|
|
|
|
}
|
|
|
|
return range2.empty();
|
|
|
|
}
|
|
|
|
|
2015-04-24 17:16:35 +00:00
|
|
|
/* algos that modify ranges or work with output ranges */
|
|
|
|
|
2015-04-21 16:56:36 +00:00
|
|
|
template<typename R1, typename R2>
|
|
|
|
R2 copy(R1 irange, R2 orange) {
|
|
|
|
for (; !irange.empty(); irange.pop_first())
|
|
|
|
orange.put(irange.first());
|
|
|
|
return orange;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R1, typename R2, typename P>
|
|
|
|
R2 copy_if(R1 irange, R2 orange, P pred) {
|
|
|
|
for (; !irange.empty(); irange.pop_first())
|
|
|
|
if (pred(irange.first()))
|
|
|
|
orange.put(irange.first());
|
|
|
|
return orange;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R1, typename R2, typename P>
|
|
|
|
R2 copy_if_not(R1 irange, R2 orange, P pred) {
|
|
|
|
for (; !irange.empty(); irange.pop_first())
|
|
|
|
if (!pred(irange.first()))
|
|
|
|
orange.put(irange.first());
|
|
|
|
return orange;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R1, typename R2>
|
|
|
|
R2 move(R1 irange, R2 orange) {
|
|
|
|
for (; !irange.empty(); irange.pop_first())
|
|
|
|
orange.put(move(irange.first()));
|
|
|
|
return orange;
|
|
|
|
}
|
|
|
|
|
2015-04-21 01:33:58 +00:00
|
|
|
template<typename R>
|
|
|
|
void reverse(R range) {
|
|
|
|
while (!range.empty()) {
|
|
|
|
swap(range.first(), range.last());
|
|
|
|
range.pop_first();
|
|
|
|
range.pop_last();
|
|
|
|
}
|
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
|
|
|
template<typename R1, typename R2>
|
|
|
|
R2 reverse_copy(R1 irange, R2 orange) {
|
|
|
|
for (; !irange.empty(); irange.pop_last())
|
|
|
|
orange.put(irange.last());
|
|
|
|
return orange;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename T>
|
|
|
|
void fill(R range, const T &v) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
range.first() = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename F>
|
|
|
|
void generate(R range, F gen) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
range.first() = gen();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R1, typename R2>
|
2015-05-26 23:49:35 +00:00
|
|
|
Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
|
|
|
while (!range1.empty() && !range2.empty()) {
|
2015-04-21 16:56:36 +00:00
|
|
|
swap(range1.first(), range2.first());
|
2015-05-26 23:49:35 +00:00
|
|
|
range1.pop_first();
|
2015-04-21 16:56:36 +00:00
|
|
|
range2.pop_first();
|
|
|
|
}
|
2015-05-26 23:49:35 +00:00
|
|
|
return Pair<R1, R2>(range1, range2);
|
2015-04-21 16:56:36 +00:00
|
|
|
}
|
2015-04-21 22:54:09 +00:00
|
|
|
|
|
|
|
template<typename R, typename T>
|
|
|
|
void iota(R range, T value) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
range.first() = value++;
|
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-05-25 19:46:49 +00:00
|
|
|
template<typename R, typename T>
|
|
|
|
T foldl(R range, T init) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
init = init + range.first();
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename T, typename F>
|
|
|
|
T foldl(R range, T init, F func) {
|
|
|
|
for (; !range.empty(); range.pop_first())
|
|
|
|
init = func(init, range.first());
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename T>
|
|
|
|
T foldr(R range, T init) {
|
|
|
|
for (; !range.empty(); range.pop_last())
|
|
|
|
init = init + range.last();
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename R, typename T, typename F>
|
|
|
|
T foldr(R range, T init, F func) {
|
|
|
|
for (; !range.empty(); range.pop_last())
|
|
|
|
init = func(init, range.last());
|
|
|
|
return init;
|
|
|
|
}
|
|
|
|
|
2015-05-24 13:34:37 +00:00
|
|
|
template<typename T, typename R>
|
2015-05-23 17:44:06 +00:00
|
|
|
struct MapRange: InputRange<
|
2015-05-24 13:34:37 +00:00
|
|
|
MapRange<T, R>, RangeCategory<T>, R, R, RangeSize<T>
|
2015-05-23 17:44:06 +00:00
|
|
|
> {
|
|
|
|
private:
|
|
|
|
T p_range;
|
2015-05-24 13:34:37 +00:00
|
|
|
Function<R(RangeReference<T>)> p_func;
|
2015-05-23 17:44:06 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
MapRange(): p_range(), p_func() {}
|
|
|
|
template<typename F>
|
|
|
|
MapRange(const T &range, const F &func): p_range(range), p_func(func) {}
|
|
|
|
MapRange(const MapRange &it): p_range(it.p_range), p_func(it.p_func) {}
|
|
|
|
MapRange(MapRange &&it): p_range(move(it.p_range)), p_func(move(it.p_func)) {}
|
|
|
|
|
|
|
|
MapRange &operator=(const MapRange &v) {
|
|
|
|
p_range = v.p_range;
|
|
|
|
p_func = v.p_func;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
MapRange &operator=(MapRange &&v) {
|
2015-05-24 01:31:54 +00:00
|
|
|
p_range = move(v.p_range);
|
2015-05-23 17:44:06 +00:00
|
|
|
p_func = move(v.p_func);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty() const { return p_range.empty(); }
|
2015-05-23 17:55:22 +00:00
|
|
|
RangeSize<T> length() const { return p_range.length(); }
|
|
|
|
|
2015-05-23 17:44:06 +00:00
|
|
|
void pop_first() { p_range.pop_first(); }
|
2015-05-23 17:55:22 +00:00
|
|
|
void pop_last() { p_range.pop_last(); }
|
|
|
|
|
2015-05-23 17:44:06 +00:00
|
|
|
RangeSize<T> pop_first_n(RangeSize<T> n) { p_range.pop_first_n(n); }
|
2015-05-23 17:55:22 +00:00
|
|
|
RangeSize<T> pop_last_n(RangeSize<T> n) { p_range.pop_last_n(n); }
|
2015-05-23 17:44:06 +00:00
|
|
|
|
2015-05-24 13:34:37 +00:00
|
|
|
R first() const { return p_func(p_range.first()); }
|
|
|
|
R last() const { return p_func(p_range.last()); }
|
2015-05-23 17:59:14 +00:00
|
|
|
|
2015-05-24 13:34:37 +00:00
|
|
|
R first() { return p_func(p_range.first()); }
|
|
|
|
R last() { return p_func(p_range.last()); }
|
2015-05-23 17:55:22 +00:00
|
|
|
|
2015-05-24 13:34:37 +00:00
|
|
|
R operator[](RangeSize<T> idx) const {
|
2015-05-23 17:59:14 +00:00
|
|
|
return p_func(p_range[idx]);
|
|
|
|
}
|
2015-05-24 13:34:37 +00:00
|
|
|
R operator[](RangeSize<T> idx) {
|
2015-05-23 17:59:14 +00:00
|
|
|
return p_func(p_range[idx]);
|
|
|
|
}
|
2015-05-23 17:55:22 +00:00
|
|
|
|
2015-05-24 13:34:37 +00:00
|
|
|
MapRange<T, R> slice(RangeSize<T> start, RangeSize<T> end) {
|
|
|
|
return MapRange<T, R>(p_range.slice(start, end), p_func);
|
2015-05-23 17:55:22 +00:00
|
|
|
}
|
2015-05-23 17:44:06 +00:00
|
|
|
|
|
|
|
bool operator==(const MapRange &v) const {
|
|
|
|
return (p_range == v.p_range) && (p_func == v.p_func);
|
|
|
|
}
|
|
|
|
bool operator!=(const MapRange &v) const {
|
|
|
|
return (p_range != v.p_range) || (p_func != v.p_func);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename R, typename F>
|
2015-05-24 13:34:37 +00:00
|
|
|
using __OctaMapReturnType = decltype(declval<F>()(declval<RangeReference<R>>()));
|
|
|
|
|
|
|
|
template<typename R, typename F>
|
|
|
|
MapRange<R, __OctaMapReturnType<R, F>> map(R range, F func) {
|
|
|
|
return MapRange<R, __OctaMapReturnType<R, F>>(range, func);
|
2015-05-23 17:44:06 +00:00
|
|
|
}
|
2015-05-24 01:31:54 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct FilterRange: InputRange<
|
2015-05-24 13:16:20 +00:00
|
|
|
FilterRange<T>, CommonType<RangeCategory<T>, ForwardRangeTag>,
|
|
|
|
RangeValue<T>, RangeReference<T>, RangeSize<T>
|
2015-05-24 01:31:54 +00:00
|
|
|
> {
|
|
|
|
private:
|
|
|
|
T p_range;
|
|
|
|
Function<bool(RangeReference<T>)> p_pred;
|
|
|
|
|
|
|
|
void advance_valid() {
|
|
|
|
while (!p_range.empty() && !p_pred(first())) p_range.pop_first();
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
FilterRange(): p_range(), p_pred() {}
|
|
|
|
|
|
|
|
template<typename P>
|
|
|
|
FilterRange(const T &range, const P &pred): p_range(range),
|
|
|
|
p_pred(pred) {
|
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
FilterRange(const FilterRange &it): p_range(it.p_range),
|
|
|
|
p_pred(it.p_pred) {
|
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
FilterRange(FilterRange &&it): p_range(move(it.p_range)),
|
|
|
|
p_pred(move(it.p_pred)) {
|
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
|
|
|
|
FilterRange &operator=(const FilterRange &v) {
|
|
|
|
p_range = v.p_range;
|
|
|
|
p_pred = v.p_pred;
|
|
|
|
advance_valid();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
FilterRange &operator=(FilterRange &&v) {
|
|
|
|
p_range = move(v.p_range);
|
|
|
|
p_pred = move(v.p_pred);
|
|
|
|
advance_valid();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty() const { return p_range.empty(); }
|
|
|
|
|
|
|
|
void pop_first() {
|
|
|
|
p_range.pop_first();
|
|
|
|
advance_valid();
|
|
|
|
}
|
|
|
|
|
|
|
|
RangeReference<T> first() const { return p_range.first(); }
|
|
|
|
RangeReference<T> first() { return p_range.first(); }
|
|
|
|
|
|
|
|
bool operator==(const FilterRange &v) const {
|
|
|
|
return (p_range == v.p_range) && (p_pred == v.p_pred);
|
|
|
|
}
|
|
|
|
bool operator!=(const FilterRange &v) const {
|
|
|
|
return (p_range != v.p_range) || (p_pred != v.p_pred);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename R, typename P>
|
|
|
|
FilterRange<R> filter(R range, P pred) {
|
|
|
|
return FilterRange<R>(range, pred);
|
|
|
|
}
|
2015-04-18 01:35:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|