#ifndef _RC_ITER_HPP_ #define _RC_ITER_HPP_ #include #include #include #include namespace rs { template struct InvokeType { template auto Call(F f, ARGS... args) { return f(std::forward(args)...); } template void CallNoReturn(F f, ARGS... args) { f(std::forward(args)...); } template auto CallFold(F f, S s, ARGS... args) { return f(std::forward(s), std::forward(args)...); } }; template struct InvokeType> { template auto Call(F f, std::pair arg) { return f(arg.first, arg.second); } template void CallNoReturn(F f, std::pair arg) { f(arg.first, arg.second); } template auto CallFold(F f, S s, std::pair arg) { return f(std::forward(s), arg.first, arg.second); } }; template struct InvokeType> { using sequence_type = std::index_sequence_for; template auto Call(F f, std::tuple arg) { return UnpackCall(std::forward(f), arg, sequence_type{}); } template void CallNoReturn(F f, std::tuple arg) { UnpackCallNoReturn(std::forward(f), arg, sequence_type{}); } template auto CallFold(F f, S s, std::tuple arg) { return UnpackCallFold(std::forward(f), std::forward(s), arg, sequence_type{}); } template auto UnpackCall(F f, std::tuple& arg, std::index_sequence) { return f(std::get(arg)...); } template void UnpackCallNoReturn(F f, std::tuple& arg, std::index_sequence) { f(std::get(arg)...); } template auto UnpackCallFold(F f, S s, std::tuple& arg, std::index_sequence) { return f(s, std::get(arg)...); } }; template struct StdFuncType { using type = void; using return_type = void; }; template struct StdFuncType { using type = std::function; using return_type = RET; }; template struct StdFuncType { using type = std::function; using return_type = RET; }; template struct FunctionType { using type = typename StdFuncType::type; using return_type = typename StdFuncType::return_type; }; template struct FunctionType { using type = std::function; using return_type = RET; }; template struct FunctionType { using type = std::function; using return_type = RET; }; template typename TP> struct TemplateChecker { static constexpr bool value = false; }; template typename TP, typename... ARGS> struct TemplateChecker, TP> { static constexpr bool value = true; }; template struct iterator { using value_type = T; std::optional next() { return iter(); } size_t count() { size_t result = 0; for (auto n = next(); n.has_value(); n = next()) result++; return result; } std::optional nth(size_t n) { while (true) { std::optional value = next(); if (n-- == 0 || !value.has_value()) return value; } } std::optional last() { std::optional value; for (auto n = next(); n.has_value(); n = next()) value = n; return value; } auto step_by(int32_t s) { return iterator{[s, c = s, it = std::move(iter)]() mutable -> auto { for (; c < s; c++) it(); c = 1; return it(); }}; } auto chain(iterator&& i) { return iterator{[it1 = std::move(iter), it2 = std::move(i.iter), s = true]() mutable -> auto { if (s) { auto v = it1(true); if (!v.has_value()) { s = false; return it2(true); } } else return it2(true); }}; } template auto zip(iterator&& i) { return iterator>{[it1 = std::move(iter), it2 = std::move(i.iter)]() mutable -> auto { if(auto v1 = it1(); v1.has_value()) { if(auto v2 = it2(); v2.has_value()) return std::optional>(std::make_pair(v1.value(), v2.value())); } return std::optional>(); }}; } template void for_each(F f) { for(auto v = next(); v.has_value(); v = next()) { InvokeType().CallNoReturn(std::ref(f), v.value()); } } template auto filter(F f) { return iterator{[f, it = std::move(iter)]() mutable -> auto { auto value = it(); while(value.has_value() && !InvokeType().Call(std::ref(f), value.value())) value = it(); return value; }}; } template auto map(M m) { using RET = typename FunctionType::return_type; return iterator{[m, it = std::move(iter)]() -> auto { auto t = it(); if (t.has_value()) return std::optional(InvokeType().Call(std::ref(m), t.value())); return std::optional(); }}; } template auto filter_map(FM fm) { using OPT = typename FunctionType::return_type; static_assert(TemplateChecker::value, "filter_map: filter must return an optional value."); using RET = typename OPT::value_type; return iterator{[fm, it = std::move(iter)]() -> auto { auto value = it(); while (value.has_value()) { if(auto mvalue = InvokeType().Call(std::ref(fm), value.value()); mvalue.has_value()) return mvalue; value = it(); } return std::optional(); }}; } auto enumerate() { return iterator>{[it = std::move(iter), i = 0]() mutable -> auto { if(auto v = it(); v.has_value()) return std::optional>(std::make_pair(i++, v.value())); return std::optional>(); }}; } auto skip(size_t n) { return iterator{[n, it = std::move(iter)]() mutable -> auto { while (n > 0) { n--; it(); } return it(); }}; } auto take(size_t n) { return iterator{[n, it = std::move(iter)]() mutable -> auto { if (n > 0) { n--; return it(); } return std::optional(); }}; } template auto skip_while(F f) { return iterator{[f, it = std::move(iter), res = false]() mutable -> auto { auto v = it(); if(res) return v; while(v.has_value() && InvokeType().Call(std::ref(f), v.value())) v = it(); res = true; return v; }}; } template auto take_while(F f) { return iterator{[f, it = std::move(iter), res = true]() mutable -> auto { if (res) { if(auto v = it(); v.has_value() && InvokeType().Call(std::ref(f), v.value())) return v; else res = false; } return std::optional(); }}; } template auto scan(S s, M m) { using RET = typename FunctionType::return_type; return iterator{[s, m, it = std::move(iter)]() mutable -> auto { auto t = it(); if(t.has_value()) return std::optional(InvokeType().CallFold(std::ref(m), std::ref(s), t.value())); return std::optional(); }}; } template auto flat_map(M m) { return map(m).flatten(); } auto flatten() { static_assert(TemplateChecker::value, "flatten: value type can only be iterator type."); using NT = typename T::value_type; return iterator{[inited = false, cur = std::optional>(), it = std::move(iter)]() mutable -> auto { if(!inited) { cur = it(); inited = true; } if(!cur.has_value()) return std::optional(); auto v = cur.value().next(); while(!v.has_value() && cur.has_value()) { cur = it(); if(cur.has_value()) v = cur.value().next(); } return v; }}; } auto fuse() { return iterator{[end = false, it = std::move(iter)]() mutable -> auto { if (end) return std::optional(); auto v = it(); if(!it.has_value()) end = true; return v; }}; } template auto inspect(F f) { return iterator{[f, it = std::move(iter)]() -> auto { auto v = it(); if(v.has_value()) InvokeType().CallNoReturn(std::ref(f), v.value()); return v; }}; } template auto collect() { C container; for (auto v = next(); v.has_value(); v = next()) container.collect_item(v.value()); return container; } template C& collect(C& container) { for (auto v = next(); v.has_value(); v = next()) container.collect_item(v.value()); return container; } template auto partition(F f) { std::pair result; for (auto v = next(); v.has_value(); v = next()) { if(InvokeType().CallNoReturn(std::ref(f), v.value())) result.first.collect_item(v.value()); else result.second.collect_item(v.value()); } return result; } template auto fold(S s, F f) { using RET = typename FunctionType::return_type; static_assert(std::is_same::value, "fold: function should return same type as value."); for (auto v = next(); v.has_value(); v = next()) { s = InvokeType().CallFold(std::ref(f), s, v.value()); } return s; } template bool all(F f) { for (auto v = next(); v.has_value(); v = next()) { if(!InvokeType().Call(std::ref(f), v.value())) return false; } return true; } template bool any(F f) { for (auto v = next(); v.has_value(); v = next()) { if(InvokeType().Call(std::ref(f), v.value())) return true; } return false; } template auto find(F f) { for (auto v = next(); v.has_value(); v = next()) { if(InvokeType().Call(std::ref(f), v.value())) return v; } return std::optional(); } template auto find_map(F f) { using OPT = typename FunctionType::return_type; static_assert(TemplateChecker::value, "find_map: filter must return an optional value."); using RET = typename OPT::value_type; for (auto v = next(); v.has_value(); v = next()) { if(auto mv = InvokeType().Call(std::ref(f), v.value()); mv.has_value()) return mv; } return std::optional(); } template auto position(F f) { size_t i = 0; for (auto v = next(); v.has_value(); v = next(), i++) { if(InvokeType().Call(std::ref(f), v.value())) return std::optional(i); } return std::optional(); } auto max() { auto res = next(); if(!res.has_value()) return res; for (auto v = next(); v.has_value(); v = next()) { if(v.value() >= res.value()) res = v; } return res; } auto min() { auto res = next(); if(!res.has_value()) return res; for (auto v = next(); v.has_value(); v = next()) { if(v.value() < res.value()) res = v; } return res; } template auto max_by_key(F f) { auto res = next(); if(!res.has_value()) return res; for (auto v = next(); v.has_value(); v = next()) { if(InvokeType().Call(std::ref(f), v.value()) >= InvokeType().Call(std::ref(f), res.value())) res = v; } return res; } template auto min_by_key(F f) { auto res = next(); if(!res.has_value()) return res; for (auto v = next(); v.has_value(); v = next()) { if(InvokeType().Call(std::ref(f), v.value()) < InvokeType().Call(std::ref(f), res.value())) res = v; } return res; } auto unzip() { static_assert(TemplateChecker::value, "unzip: iterator type must be pair"); using TP1 = typename T::first_type; using TP2 = typename T::second_type; std::pair, iterator> result; result.first.iter = [it = iter]()-> auto { auto v = it(); return v.has_value() ? std::optional(v.value().first): std::optional(); }; result.second.iter = [it = iter]()-> auto { auto v = it(); return v.has_value() ? std::optional(v.value().second): std::optional(); }; return result; } auto cycle() { return iterator{[it = iter, it2 = iter]() mutable -> auto { auto v = it(false); if(v.has_value()) return v; it = it2; return it(false); }}; } auto sum() { auto res = T(0); for (auto v = next(); v.has_value(); v = next()) res += v.value(); return res; } auto product() { auto res = T(1); for (auto v = next(); v.has_value(); v = next()) res *= v.value(); return res; } std::function()> iter; }; template auto range(T start, T end) { return iterator{[start, end]() mutable -> auto { if(start >= end) return std::optional(); return std::optional(start++); }}; } template auto repeat(T value) { return iterator{[value]() -> auto { return std::optional(value); }}; } } // namespace rs #endif