VC10β2で先取りしたC++0xの機能を用いてHaskell風に書けるようにするためのライブラリ。一部は趣味でPython風の名前になっていたりする。ここを常に参照することにする。勝手に追加される。
破壊的な変更がされる場合は別にエントリーを立てる。
// // itertools.h // by M.Inamori // written 3/15/10 // reviced 4/30/10 #pragma once #include <vector> #include <tuple> #include <string> #include <set> #include <type_traits> #include <algorithm> namespace itertools { // reduce template<typename T, typename U, typename V> V reduce(T f, U& g, V x) { while(true) { if(g.exists_next()) x = f(x, g.next()); else return x; } } template<typename T, typename U> auto reduce1(T f, U& g) -> decltype(g.next()) { if(!g.exists_next()) throw("error : 2nd argument of reduce1 is empty."); auto x = g.next(); while(true) { if(g.exists_next()) x = f(x, g.next()); else return x; } } // iterate template<typename T, typename U> class cIterate { T& func_obj; U v; public: cIterate(T& fo, U v) : func_obj(fo), v(v) { } U next() { U tmp = v; v = func_obj(v); return tmp; } bool exists_next() { return true; } }; template<typename T, typename U> cIterate<T,U> iterate(T& fo, U v) { return cIterate<T,U>(fo, v); } // iter template<typename T, typename U> void iter(T& f, U& g) { while(g.exists_next()) f(g.next()); } // map template<typename T, typename U, typename V> class cMap { T& func; U& gen; public: cMap(T& f, U& g) : func(f), gen(g) { } V next() { return func(gen.next()); } bool exists_next() { return gen.exists_next(); } }; template<typename T, typename U> auto map(T& func, U& gen) -> cMap<T,U,decltype(func(gen.next()))>{ return cMap<T,U,decltype(func(gen.next()))>(func, gen); } // filter template<typename T, typename U, typename V> class cFilter { T& pred; U& gen; V v; bool bexists; bool searched; public: cFilter(T& p, U& g) : pred(p), gen(g), searched(false) { } V next() { if(!searched) { if(!exists_next()) throw("error : 2nd argument of filter is empty."); } searched = false; return v; } bool exists_next() { if(searched) { return bexists; } else { while(gen.exists_next()) { v = gen.next(); if(pred(v)) { bexists = true; searched = true; return true; } } bexists = false; searched = true; return false; } } }; template<typename T, typename U> auto filter(T& pred, U& gen) -> cFilter<T,U,decltype(gen.next())> { return cFilter<T,U,decltype(gen.next())>(pred, gen); } // takewhile template<typename T, typename U, typename V> class cTakeWhile { T& pred; U& gen; V v; bool bexists; bool searched; public: cTakeWhile(T& p, U& g) : pred(p), gen(g), searched(false) { } V next() { if(!searched) { if(!exists_next()) throw("error : 2nd argument of filter is empty."); } searched = false; return v; } bool exists_next() { if(searched) { return bexists; } else { if(gen.exists_next()) { v = gen.next(); if(pred(v)) { bexists = true; searched = true; return true; } } bexists = false; searched = true; return false; } } }; template<typename T, typename U> auto takewhile(T& pred, U& gen) -> cTakeWhile<T,U,decltype(gen.next())> { return cTakeWhile<T,U,decltype(gen.next())>(pred, gen); } // all template<typename T, typename U> bool all(T& f, U& g) { while(g.exists_next()) { if(!f(g.next())) return false; } return true; } // any template<typename T, typename U> bool any(T& f, U& g) { while(g.exists_next()) { if(f(g.next())) return true; } return false; } // head template<typename T> auto head(T& g) -> decltype(g.next()) { if(!g.exists_next()) throw("error : the argument of head is empty."); return g.next(); } // last template<typename T> auto last(T& g) ->decltype(g.next()) { if(!g.exists_next()) throw("error : the argument of last is empty."); auto v = g.next(); while(g.exists_next()) v = g.next(); return v; } // take template<typename T, typename U> class cTake { T& gen; int counter; public: cTake(int n, T& g) : counter(n), gen(g) { } U next() { counter--; return gen.next(); } bool exists_next() { return counter > 0 && gen.exists_next(); } }; template<typename T> auto take(int n, T& g) -> cTake<T,decltype(g.next())> { return cTake<T,decltype(g.next())>(n, g); } // length template<typename T> int length(T& g) { return g.exists_next() ? fst(last(zip(count<>(1), g))) : 0; } // zip template<typename T, typename U, typename V, typename W> class cZip { T& gen1; U& gen2; std::tuple<V,W> v; public: cZip(T& g1, U& g2) : gen1(g1), gen2(g2) { } std::tuple<V,W> next() { return std::make_tuple(gen1.next(), gen2.next()); } bool exists_next() { return gen1.exists_next() && gen2.exists_next(); } }; template<typename T, typename U> auto zip(T& g1, U& g2) -> cZip<T,U,decltype(g1.next()),decltype(g2.next())> { return cZip<T,U,decltype(g1.next()),decltype(g2.next())>(g1, g2); } // cat template<typename T, typename U, typename V> class cConcatenate { U& gen1; V& gen2; bool first; public: cConcatenate(U& g1, V& g2) : gen1(g1), gen2(g2), first(true) { } T next() { return first ? gen1.next() : gen2.next(); } bool exists_next() { if(first) { if(gen1.exists_next()) { return true; } else { first = false; return gen2.exists_next(); } } else { return gen2.exists_next(); } } }; template<typename U, typename V> auto cat(U& g1, V& g2) -> cConcatenate<decltype(g1.next()), U, V> { return cConcatenate<decltype(g1.next()), U, V>(g1, g2); } // product template<typename T, typename U, typename V, typename W> class cProduct { U& gen; T gen1; U gen2; V v; public: cProduct(T& g1, U& g2) : gen(g2), gen1(g1), gen2(g2) { v = gen1.next(); } std::tuple<V,W> next() { if(gen2.exists_next()) { return make_tuple(v, gen2.next()); } else { v = gen1.next(); gen2 = gen; return next(); } } bool exists_next() { return gen2.exists_next() || gen1.exists_next(); } }; template<typename T, typename U, typename V, typename W, typename X> class cDependentlyProduct { T& gen1; X& fo; U gen2; V v; public: cDependentlyProduct(T& g1, X& g) : gen1(g1), fo(g) { v = gen1.next(); gen2 = fo(v); } std::tuple<V,W> next() { if(gen2.exists_next()) { return std::make_tuple(v, gen2.next()); } else { v = gen1.next(); gen2 = fo(v); return next(); } } bool exists_next() { return gen2.exists_next() || gen1.exists_next(); } }; template<typename T> class has_paren { typedef char yes; typedef struct { char a[2]; } no; template<typename U> static yes test(U *g, decltype(g->operator())); template<typename U> static no test(...); public: static const bool value = sizeof(test<T>(0, 0)) == sizeof(yes); }; template<typename T, typename X> auto product(T& g, X& fo, typename std::enable_if<has_paren<X>::value,X>::type* = 0) -> cDependentlyProduct<T,decltype(fo(g.next())),decltype(g.next()), decltype(fo(g.next()).next()),X> { return cDependentlyProduct<T,decltype(fo(g.next())), decltype(g.next()), decltype(fo(g.next()).next()),X>(g,fo); } template<typename T, typename U> auto product(T& g, U& g2, ...) -> cProduct<T,U,decltype(g.next()),decltype(g2.next())> { return cProduct<T,U,decltype(g.next()),decltype(g2.next())>(g,g2); } template<typename T> auto product(T& g, ...) -> cProduct<T,T,decltype(g.next()),decltype(g.next())> { return cProduct<T,T,decltype(g.next()),decltype(g.next())>(g,g); } // fst template<typename T, typename U> T fst(std::tuple<T,U> t) { return std::get<0>(t); } // snd template<typename T, typename U> U snd(std::tuple<T,U> t) { return std::get<1>(t); } // range template<typename T = int> class range { T current; T end; T delta; public: range(T b, T e, T d = 1) : current(b), end(e), delta(d) { } range(T e) : current(0), end(e), delta(1) { } range() : current(0), end(0), delta(0) { } T next() { if(current < end) { T v = current; current += delta; return v; } else { throw("error : no more elements in range."); } } bool exists_next() { return current < end; } }; // count template<typename T = int> class count { T current; T delta; public: count(T b, T d = 1) : current(b), delta(d) { } count() : current(0), delta(1) { } T next() { T v = current; current += delta; return v; } bool exists_next() { return true; } }; // sum template<typename T> auto sum(T& gen) -> decltype(gen.next()) { decltype(gen.next()) s = 0; while(gen.exists_next()) s += gen.next(); return s; } // list template<typename T> auto list(T g) -> std::vector<decltype(g.next())> { std::vector<decltype(g.next())> v; while(g.exists_next()) v.push_back(g.next()); return v; } // iterable template<typename T, typename U> class cIterable { U current; U end; public: cIterable(U b, U e) : current(b), end(e) { } T next() { return *(current++); } bool exists_next() { return current != end; } }; template<typename T> auto iterable(const std::vector<T>& v) -> cIterable<T,decltype(v.begin())> { return cIterable<T,decltype(v.begin())>(v.begin(), v.end()); } template<typename T> auto iterable(const std::set<T>& s) -> cIterable<T,decltype(s.begin())> { return cIterable<T,decltype(s.begin())>(s.begin(), s.end()); } template<typename T> auto iterable(T begin, T end) -> cIterable<decltype(*begin), T> { return cIterable<decltype(*begin), T>(begin, end); } // reversed template<typename T> class cReversed { const std::vector<T>& v; int k; public: cReversed(const std::vector<T>& v) : v(v), k((int)v.size() - 1) { } T next() { if(k == -1) throw("error : no more elements in reversed."); return v[k--]; } bool exists_next() { return k >= 0; } }; template<typename T> cReversed<T> reversed(const std::vector<T>& v) { return cReversed<T>(v); } template<typename T, typename U> class cSorted { std::vector<T> sorted_vector; typename std::vector<T>::const_iterator current; public: cSorted(const std::vector<T>& v) { sorted_vector = v; std::sort(sorted_vector.begin(), sorted_vector.end()); current = sorted_vector.begin(); } cSorted(const std::vector<T>& v, U& cmp) { sorted_vector = v; std::sort(sorted_vector.begin(), sorted_vector.end(), cmp); current = sorted_vector.begin(); } T next() { return *(current++); } bool exists_next() { return current != sorted_vector.end(); } }; template<typename T> cSorted<T,int> sorted(const std::vector<T>& v) { return cSorted<T,int>(v); } template<typename T, typename U> cSorted<T,U> sorted(const std::vector<T>& v, U cmp) { return cSorted<T,U>(v, cmp); } // 関数を関数オブジェクトに変換 template<typename T, typename U> class cFuncObj { U (*func)(T); public: cFuncObj(U (*f)(T)) : func(f) { } U operator()(T x) { return func(x); } }; template<typename T, typename U> cFuncObj<T,U> func_obj(U (*f)(T)) { return cFuncObj<T,U>(f); } // 10進関係 template<typename T, int B = 10> class cDigits { T n; public: cDigits(T n = 0) : n(n) { } int next() { if(n == 0) throw("error : no more elements in digits."); int r = n % B; n /= B; return r; } bool exists_next() { return n != 0; } }; template<typename T, int B> cDigits<T,B> digits(T n) { return cDigits<T,B>(n); } template<typename T> cDigits<T> digits(T n) { return cDigits<T>(n); } // 数字の並びを変えない template<typename T, int B = 10> class cDigits2 { std::vector<T> v; typename std::vector<T>::reverse_iterator p; public: cDigits2(T n) { v = list(digits(n)); p = v.rbegin(); } int next() { return *(p++); } bool exists_next() { return p != v.rend(); } }; template<typename T, int B> cDigits2<T,B> digits2(T n) { return cDigits2<T,B>(n); } template<typename T> cDigits2<T> digits2(T n) { return cDigits2<T>(n); } template<typename T, typename U, int B> T to_number(U& g) { return reduce([] (T x, int y) { return (T)(x * B + y); }, g, (T)0); } template<typename T> auto to_number(T& g) -> decltype(g.next()) { typedef decltype(g.next()) U; return reduce([] (U x, U y) { return x * 10 + y; }, g, (U)0); } #if 0 template<typename T> T to_number(const std::vector<T>& v) { return to_number(iterable(v)); } #endif // words class words { const char *str; public: words(const char *s) : str(s) { } std::string next() { const char *p = str; int mode = 0; for( ; *p != '\0'; ++p) { char c = *p; if(mode == 0) { if(c != ' ') { str = p; mode = 1; } } else { if(c == ' ') { char *str2 = new char[p-str+1]; strncpy(str2, str, p - str); *(str2 + (p - str)) = '\0'; str = p + 1; std::string s = str2; delete str2; return s; } } } if(mode == 1) { char *str2 = new char[p-str+1]; strncpy(str2, str, p - str + 1); str = p; std::string s = str2; delete str2; return s; } else { throw(1); } } bool exists_next() { return *str != '\0'; } }; }