/* Algorithms for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OCTA_ALGORITHM_H #define OCTA_ALGORITHM_H #include #include "octa/functional.h" #include "octa/range.h" #include "octa/utility.h" #include "octa/initializer_list.h" namespace octa { /* partitioning */ template _R partition(_R __range, _U __pred) { _R __ret = __range; for (; !__range.empty(); __range.pop_front()) { if (__pred(__range.front())) { octa::swap(__range.front(), __ret.front()); __ret.pop_front(); } } return __ret; } template bool is_partitioned(_R __range, _P __pred) { for (; !__range.empty() && __pred(__range.front()); __range.pop_front()); for (; !__range.empty(); __range.pop_front()) if (__pred(__range.front())) return false; return true; } /* sorting */ template void __octa_insort(_R __range, _C __compare) { octa::RangeSize<_R> __rlen = __range.size(); for (octa::RangeSize<_R> __i = 1; __i < __rlen; ++__i) { octa::RangeSize<_R> __j = __i; octa::RangeReference<_R> __v = __range[__i]; while (__j > 0 && !__compare(__range[__j - 1], __v)) { __range[__j] = __range[__j - 1]; --__j; } __range[__j] = __v; } } template struct __OctaUnaryCompare { const _T &__val; _U __comp; bool operator()(const _T &__v) const { return __comp(__v, __val); } }; template void __octa_hs_sift_down(_R __range, octa::RangeSize<_R> __s, octa::RangeSize<_R> __e, _C __compare) { octa::RangeSize<_R> __r = __s; while ((__r * 2 + 1) <= __e) { octa::RangeSize<_R> __ch = __r * 2 + 1; octa::RangeSize<_R> __sw = __r; if (__compare(__range[__sw], __range[__ch])) __sw = __ch; if (((__ch + 1) <= __e) && __compare(__range[__sw], __range[__ch + 1])) __sw = __ch + 1; if (__sw != __r) { octa::swap(__range[__r], __range[__sw]); __r = __sw; } else return; } } template void __octa_heapsort(_R __range, _C __compare) { octa::RangeSize<_R> __len = __range.size(); octa::RangeSize<_R> __st = (__len - 2) / 2; for (;;) { __octa_hs_sift_down(__range, __st, __len - 1, __compare); if (__st-- == 0) break; } octa::RangeSize<_R> __e = __len - 1; while (__e > 0) { octa::swap(__range[__e], __range[0]); --__e; __octa_hs_sift_down(__range, 0, __e, __compare); } } template void __octa_introloop(_R __range, _C __compare, RangeSize<_R> __depth) { if (__range.size() <= 10) { __octa_insort(__range, __compare); return; } if (__depth == 0) { __octa_heapsort(__range, __compare); return; } octa::RangeReference<_R> __p = __range[__range.size() / 2]; octa::swap(__p, __range.back()); _R __r = octa::partition(__range, __OctaUnaryCompare{ __p, __compare }); _R __l = __range.slice(0, __range.size() - __r.size()); octa::swap(__r.front(), __r.back()); __octa_introloop(__l, __compare, __depth - 1); __octa_introloop(__r, __compare, __depth - 1); } template void __octa_introsort(_R __range, _C __compare) { __octa_introloop(__range, __compare, octa::RangeSize<_R>(2 * (log(__range.size()) / log(2)))); } template void sort(_R __range, _C __compare) { __octa_introsort(__range, __compare); } template void sort(_R __range) { sort(__range, octa::Less>()); } /* min/max(_element) */ template inline const _T &min(const _T &__a, const _T &__b) { return (__a < __b) ? __a : __b; } template inline const _T &min(const _T &__a, const _T &__b, _C __compare) { return __compare(__a, __b) ? __a : __b; } template inline const _T &max(const _T &__a, const _T &__b) { return (__a < __b) ? __b : __a; } template inline const _T &max(const _T &__a, const _T &__b, _C __compare) { return __compare(__a, __b) ? __b : __a; } template inline _R min_element(_R __range) { _R __r = __range; for (; !__range.empty(); __range.pop_front()) if (octa::min(__r.front(), __range.front()) == __range.front()) __r = __range; return __r; } template inline _R min_element(_R __range, _C __compare) { _R __r = __range; for (; !__range.empty(); __range.pop_front()) if (octa::min(__r.front(), __range.front(), __compare) == __range.front()) __r = __range; return __r; } template inline _R max_element(_R __range) { _R __r = __range; for (; !__range.empty(); __range.pop_front()) if (octa::max(__r.front(), __range.front()) == __range.front()) __r = __range; return __r; } template inline _R max_element(_R __range, _C __compare) { _R __r = __range; for (; !__range.empty(); __range.pop_front()) if (octa::max(__r.front(), __range.front(), __compare) == __range.front()) __r = __range; return __r; } template inline _T min(std::initializer_list<_T> __il) { return octa::min_element(octa::each(__il)).front(); } template inline _T min(std::initializer_list<_T> __il, _C __compare) { return octa::min_element(octa::each(__il), __compare).front(); } template inline _T max(std::initializer_list<_T> __il) { return octa::max_element(octa::each(__il)).front(); } template inline _T max(std::initializer_list<_T> __il, _C __compare) { return octa::max_element(octa::each(__il), __compare).front(); } /* clamp */ template inline _T clamp(const _T &__v, const _U &__lo, const _U &__hi) { return octa::max(_T(__lo), octa::min(__v, _T(__hi))); } template inline _T clamp(const _T &__v, const _U &__lo, const _U &__hi, _C __compare) { return octa::max(_T(__lo), octa::min(__v, _T(__hi), __compare), __compare); } /* algos that don't change the range */ template _F for_each(_R __range, _F __func) { for (; !__range.empty(); __range.pop_front()) __func(__range.front()); return octa::move(__func); } template bool all_of(_R __range, _P __pred) { for (; !__range.empty(); __range.pop_front()) if (!__pred(__range.front())) return false; return true; } template bool any_of(_R __range, _P __pred) { for (; !__range.empty(); __range.pop_front()) if (__pred(__range.front())) return true; return false; } template bool none_of(_R __range, _P __pred) { for (; !__range.empty(); __range.pop_front()) if (__pred(__range.front())) return false; return true; } template _R find(_R __range, const _T &__v) { for (; !__range.empty(); __range.pop_front()) if (__range.front() == __v) break; return __range; } template _R find_if(_R __range, _P __pred) { for (; !__range.empty(); __range.pop_front()) if (__pred(__range.front())) break; return __range; } template _R find_if_not(_R __range, _P __pred) { for (; !__range.empty(); __range.pop_front()) if (!__pred(__range.front())) break; return __range; } template RangeSize<_R> count(_R __range, const _T &__v) { RangeSize<_R> __ret = 0; for (; !__range.empty(); __range.pop_front()) if (__range.front() == __v) ++__ret; return __ret; } template RangeSize<_R> count_if(_R __range, _P __pred) { RangeSize<_R> __ret = 0; for (; !__range.empty(); __range.pop_front()) if (__pred(__range.front())) ++__ret; return __ret; } template RangeSize<_R> count_if_not(_R __range, _P __pred) { RangeSize<_R> __ret = 0; for (; !__range.empty(); __range.pop_front()) if (!__pred(__range.front())) ++__ret; return __ret; } template bool equal(_R __range1, _R __range2) { for (; !__range1.empty(); __range1.pop_front()) { if (__range2.empty() || (__range1.front() != __range2.front())) return false; __range2.pop_front(); } return __range2.empty(); } /* algos that modify ranges or work with output ranges */ template _R2 copy(_R1 __irange, _R2 __orange) { for (; !__irange.empty(); __irange.pop_front()) __orange.put(__irange.front()); return __orange; } template _R2 copy_if(_R1 __irange, _R2 __orange, _P __pred) { for (; !__irange.empty(); __irange.pop_front()) if (__pred(__irange.front())) __orange.put(__irange.front()); return __orange; } template _R2 copy_if_not(_R1 __irange, _R2 __orange, _P __pred) { for (; !__irange.empty(); __irange.pop_front()) if (!__pred(__irange.front())) __orange.put(__irange.front()); return __orange; } template _R2 move(_R1 __irange, _R2 __orange) { for (; !__irange.empty(); __irange.pop_front()) __orange.put(octa::move(__irange.front())); return __orange; } template void reverse(_R __range) { while (!__range.empty()) { octa::swap(__range.front(), __range.back()); __range.pop_front(); __range.pop_back(); } } template _R2 reverse_copy(_R1 __irange, _R2 __orange) { for (; !__irange.empty(); __irange.pop_back()) __orange.put(__irange.back()); return __orange; } template void fill(_R __range, const _T &__v) { for (; !__range.empty(); __range.pop_front()) __range.front() = __v; } template void generate(_R __range, _F __gen) { for (; !__range.empty(); __range.pop_front()) __range.front() = __gen(); } template octa::Pair<_R1, _R2> swap_ranges(_R1 __range1, _R2 __range2) { while (!__range1.empty() && !__range2.empty()) { octa::swap(__range1.front(), __range2.front()); __range1.pop_front(); __range2.pop_front(); } return octa::make_pair(__range1, __range2); } template void iota(_R __range, _T __value) { for (; !__range.empty(); __range.pop_front()) __range.front() = __value++; } template _T foldl(_R __range, _T __init) { for (; !__range.empty(); __range.pop_front()) __init = __init + __range.front(); return __init; } template _T foldl(_R __range, _T __init, _F __func) { for (; !__range.empty(); __range.pop_front()) __init = __func(__init, __range.front()); return __init; } template _T foldr(_R __range, _T __init) { for (; !__range.empty(); __range.pop_back()) __init = __init + __range.back(); return __init; } template _T foldr(_R __range, _T __init, _F __func) { for (; !__range.empty(); __range.pop_back()) __init = __func(__init, __range.back()); return __init; } template struct MapRange: InputRange< MapRange<_T, _R>, octa::RangeCategory<_T>, _R, _R, octa::RangeSize<_T> > { private: _T __range; octa::Function<_R(octa::RangeReference<_T>)> __func; public: MapRange(): __range(), __func() {} template MapRange(const _T &__range, const _F &__func): __range(__range), __func(__func) {} MapRange(const MapRange &__it): __range(__it.__range), __func(__it.__func) {} MapRange(MapRange &&__it): __range(move(__it.__range)), __func(move(__it.__func)) {} MapRange &operator=(const MapRange &__v) { __range = __v.__range; __func = __v.__func; return *this; } MapRange &operator=(MapRange &&__v) { __range = move(__v.__range); __func = move(__v.__func); return *this; } bool empty() const { return __range.empty(); } octa::RangeSize<_T> size() const { return __range.size(); } bool equals_front(const MapRange &__r) const { return __range.equals_front(__r.__range); } bool equals_back(const MapRange &__r) const { return __range.equals_front(__r.__range); } octa::RangeDifference<_T> distance_front(const MapRange &__r) const { return __range.distance_front(__r.__range); } octa::RangeDifference<_T> distance_back(const MapRange &__r) const { return __range.distance_back(__r.__range); } bool pop_front() { return __range.pop_front(); } bool pop_back() { return __range.pop_back(); } bool push_front() { return __range.pop_front(); } bool push_back() { return __range.push_back(); } octa::RangeSize<_T> pop_front_n(octa::RangeSize<_T> __n) { __range.pop_front_n(__n); } octa::RangeSize<_T> pop_back_n(octa::RangeSize<_T> __n) { __range.pop_back_n(__n); } octa::RangeSize<_T> push_front_n(octa::RangeSize<_T> __n) { return __range.push_front_n(__n); } octa::RangeSize<_T> push_back_n(octa::RangeSize<_T> __n) { return __range.push_back_n(__n); } _R front() const { return __func(__range.front()); } _R back() const { return __func(__range.back()); } _R operator[](octa::RangeSize<_T> __idx) const { return __func(__range[__idx]); } MapRange<_T, _R> slice(octa::RangeSize<_T> __start, octa::RangeSize<_T> __end) { return MapRange<_T, _R>(__range.slice(__start, __end), __func); } }; template using __OctaMapReturnType = decltype(declval<_F>()(octa::declval>())); template MapRange<_R, __OctaMapReturnType<_R, _F>> map(_R __range, _F __func) { return octa::MapRange<_R, __OctaMapReturnType<_R, _F>>(__range, __func); } template struct FilterRange: InputRange< FilterRange<_T>, octa::CommonType, octa::ForwardRangeTag>, octa::RangeValue<_T>, octa::RangeReference<_T>, octa::RangeSize<_T> > { private: _T __range; octa::Function)> __pred; void advance_valid() { while (!__range.empty() && !__pred(front())) __range.pop_front(); } public: FilterRange(): __range(), __pred() {} template FilterRange(const _T &__range, const _P &__pred): __range(__range), __pred(__pred) { advance_valid(); } FilterRange(const FilterRange &__it): __range(__it.__range), __pred(__it.__pred) { advance_valid(); } FilterRange(FilterRange &&__it): __range(move(__it.__range)), __pred(move(__it.__pred)) { advance_valid(); } FilterRange &operator=(const FilterRange &__v) { __range = __v.__range; __pred = __v.__pred; advance_valid(); return *this; } FilterRange &operator=(FilterRange &&__v) { __range = move(__v.__range); __pred = move(__v.__pred); advance_valid(); return *this; } bool empty() const { return __range.empty(); } bool equals_front(const FilterRange &__r) const { return __range.equals_front(__r.__range); } bool pop_front() { bool __ret = __range.pop_front(); advance_valid(); return __ret; } bool push_front() { _T __tmp = __range; if (!__tmp.push_front()) return false; while (!pred(__tmp.front())) if (!__tmp.push_front()) return false; __range = __tmp; return true; } octa::RangeReference<_T> front() const { return __range.front(); } }; template FilterRange<_R> filter(_R __range, _P __pred) { return octa::FilterRange<_R>(__range, __pred); } } #endif