#include <iostream>
#include <tuple>
#include <utility>
#include <type_traits>
#include <functional>
#include <vector>
/*template <typename T>
struct xrange {
};*/
struct to_t { };
const auto to = to_t();
struct until_t { };
const auto until = until_t();
template <typename T>
struct set_build {
std::vector<T> items;
set_build () {
}
set_build ( std::vector<T> build ) : items(std::move(build)) {
}
typename std::vector<T>::iterator begin () {
return std::begin( items );
}
typename std::vector<T>::iterator end () {
return std::end( items );
}
typename std::vector<T>::const_iterator begin () const {
return std::begin( items );
}
typename std::vector<T>::const_iterator end () const {
return std::end( items );
}
template <typename TFx>
set_build<T> operator& ( TFx&& fx ) {
std::vector<T> filtered;
filtered.reserve( items.size() );
for ( auto&& item : items ) {
if ( fx( item ) )
filtered.emplace_back( item );
}
items = std::move( filtered );
return *this;
}
};
template <typename TFx, typename T>
set_build<T> operator| ( TFx&& fx, const set_build<T>& set ) {
std::vector<T> comprehension;
comprehension.reserve( set.items.size() );
for ( auto& item : set ) {
comprehension.emplace_back( fx( item ) );
}
return set_build<T>( std::move( comprehension ) );
}
template <typename T, typename T0, typename T1 = T0, typename TDiff = decltype( std::declval<T1>() - std::declval<T0>() )>
set_build<T> make_specific ( T0&& n0, const to_t&, T1&& n1, TDiff&& ndiff = static_cast<TDiff>(1) ) {
std::vector<T> items;
if ( n0 == n1 || ndiff == static_cast<TDiff>( 0 ) )
return set_build<T>( std::move( items ) );
T c0 = n0;
if ( n0 < n1 ) {
if ( ndiff < static_cast<TDiff>( 0 ) )
return set_build<T>( std::move( items ) );
while ( c0 <= n1 ) {
items.emplace_back( c0 );
c0 += ndiff;
}
}
else {
if ( ndiff > static_cast<TDiff>( 0 ) )
return set_build<T>( std::move( items ) );
while ( c0 >= n1 ) {
items.emplace_back( c0 );
c0 += ndiff;
}
}
return set_build<T>( std::move( items ) );
}
template <typename T0, typename T1 = T0>
set_build<T0> make ( T0&& n0, T1&& n1 ) {
return make_specific<T0, T0, T1>( std::forward<T0>( n0 ), to, std::forward<T1>( n1 ) );
}
template <typename T0, typename T1 = T0, typename TDiff = decltype( std::declval<T1>() - std::declval<T0>() )>
set_build<T0> make ( T0&& n0, const to_t&, T1&& n1, TDiff&& ndiff = static_cast<TDiff>(1) ) {
return make_specific<T0, T0, T1, TDiff>( std::forward<T0>( n0 ), to, std::forward<T1>( n1 ), std::forward<TDiff>( ndiff ) );
}
template <typename T, typename T0, typename T1 = T0, typename TLim = T0>
set_build<T> make_specific ( T0&& n0, T1&& n1, const until_t&, TLim&& nlim ) {
typedef decltype( std::declval<T1>() - std::declval<T0>() ) TDiff;
TDiff ndiff = n1 - n0;
return make_specific<T, T0, TLim, TDiff>( std::forward<T0>( n0 ), to, std::forward<TLim>( nlim ), std::forward<TDiff>( ndiff ) );
}
template <typename T0, typename T1 = T0, typename TLim = T0>
set_build<T0> make ( T0&& n0, T1&& n1, const until_t&, TLim&& nlim ) {
return make_specific<T0, T0, T1, TLim>( std::forward<T0>( n0 ), std::forward<T1>( n1 ), until, std::forward<TLim>( nlim ) );
}
template <typename T0, typename T1 = T0, typename TLim = T0>
set_build<T0> make ( T0&& n0, T1&& n1, TLim&& nlim ) {
return make_specific<T0, T0, T1, TLim>( std::forward<T0>( n0 ), std::forward<T1>( n1 ), until, std::forward<TLim>( nlim ) );
}
template <typename TRange>
void Print ( TRange&& range ) {
std::cout << "[ ";
for ( auto& r : range ) {
std::cout << r << ' ';
}
std::cout << "]" << std::endl;
}
int main ( int argc, char** argv ) {
// While the next line would be the ideal math-like syntax
// we can't have it because `operator|` is left-associative
// we, instead of the below...
//auto results = [ ( x * x ) | (1, 20) | (x * x > 144) ] ;
// we start with a range instead, so we can build it up from there
// also, in C++ we use lambdas
//auto results = [ build(1, to, 20) | ( x * x ) | (x * x > 144) ] ;
auto results1 = []( int x ) { return x * x; } | make( 1, to, 20 ) & []( int x ){ return x * x > 144; };
std::cout << "make(1, to, 20):" << std::endl;
Print( results1 );
auto results2 = []( int x ) { return x * x; } | make( 1, 2, 20 ) & []( int x ){ return x * x > 144; };
std::cout << "make(1, 2, 20):" << std::endl;
Print( results2 );
auto results3 = []( int x ) { return x * x; } | make( 1, 4, 20 ) & []( int x ){ return x * x > 144; };
std::cout << "make(1, 4, 20):" << std::endl;
Print( results3 );
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8dmVjdG9yPgoKLyp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IHhyYW5nZSB7CiAgICAKICAgIAp9OyovCgpzdHJ1Y3QgdG9fdCB7IH07CmNvbnN0IGF1dG8gdG8gPSB0b190KCk7CgpzdHJ1Y3QgdW50aWxfdCB7IH07CmNvbnN0IGF1dG8gdW50aWwgPSB1bnRpbF90KCk7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IHNldF9idWlsZCB7CiAgICBzdGQ6OnZlY3RvcjxUPiBpdGVtczsKICAgIAogICAgc2V0X2J1aWxkICgpIHsKICAgICAgICAKICAgIH0KICAgIAogICAgc2V0X2J1aWxkICggc3RkOjp2ZWN0b3I8VD4gYnVpbGQgKSA6IGl0ZW1zKHN0ZDo6bW92ZShidWlsZCkpIHsKICAgICAgICAKICAgIH0KICAgIAogICAgdHlwZW5hbWUgc3RkOjp2ZWN0b3I8VD46Oml0ZXJhdG9yIGJlZ2luICgpIHsKICAgICAgICByZXR1cm4gc3RkOjpiZWdpbiggaXRlbXMgKTsKICAgIH0KICAgIAogICAgdHlwZW5hbWUgc3RkOjp2ZWN0b3I8VD46Oml0ZXJhdG9yIGVuZCAoKSB7CiAgICAgICAgcmV0dXJuIHN0ZDo6ZW5kKCBpdGVtcyApOwogICAgfQogICAgCiAgICB0eXBlbmFtZSBzdGQ6OnZlY3RvcjxUPjo6Y29uc3RfaXRlcmF0b3IgYmVnaW4gKCkgY29uc3QgewogICAgICAgIHJldHVybiBzdGQ6OmJlZ2luKCBpdGVtcyApOwogICAgfQogICAgCiAgICB0eXBlbmFtZSBzdGQ6OnZlY3RvcjxUPjo6Y29uc3RfaXRlcmF0b3IgZW5kICgpIGNvbnN0IHsKICAgICAgICByZXR1cm4gc3RkOjplbmQoIGl0ZW1zICk7CiAgICB9CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFRGeD4KICAgIHNldF9idWlsZDxUPiBvcGVyYXRvciYgKCBURngmJiBmeCApIHsKICAgICAgICBzdGQ6OnZlY3RvcjxUPiBmaWx0ZXJlZDsKICAgICAgICBmaWx0ZXJlZC5yZXNlcnZlKCBpdGVtcy5zaXplKCkgKTsKICAgICAgICBmb3IgKCBhdXRvJiYgaXRlbSA6IGl0ZW1zICkgewogICAgICAgICAgICBpZiAoIGZ4KCBpdGVtICkgKQogICAgICAgICAgICAgICAgZmlsdGVyZWQuZW1wbGFjZV9iYWNrKCBpdGVtICk7CiAgICAgICAgfQogICAgICAgIGl0ZW1zID0gc3RkOjptb3ZlKCBmaWx0ZXJlZCApOwogICAgICAgIHJldHVybiAqdGhpczsKICAgIH0KICAgIAp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFRGeCwgdHlwZW5hbWUgVD4Kc2V0X2J1aWxkPFQ+IG9wZXJhdG9yfCAoIFRGeCYmIGZ4LCBjb25zdCBzZXRfYnVpbGQ8VD4mIHNldCApIHsKICAgIHN0ZDo6dmVjdG9yPFQ+IGNvbXByZWhlbnNpb247CiAgICBjb21wcmVoZW5zaW9uLnJlc2VydmUoIHNldC5pdGVtcy5zaXplKCkgKTsKICAgIGZvciAoIGF1dG8mIGl0ZW0gOiBzZXQgKSB7CiAgICAgICBjb21wcmVoZW5zaW9uLmVtcGxhY2VfYmFjayggZngoIGl0ZW0gKSApOwogICAgfQogICAgcmV0dXJuIHNldF9idWlsZDxUPiggc3RkOjptb3ZlKCBjb21wcmVoZW5zaW9uICkgKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFQwLCB0eXBlbmFtZSBUMSA9IFQwLCB0eXBlbmFtZSBURGlmZiA9IGRlY2x0eXBlKCBzdGQ6OmRlY2x2YWw8VDE+KCkgLSBzdGQ6OmRlY2x2YWw8VDA+KCkgKT4Kc2V0X2J1aWxkPFQ+IG1ha2Vfc3BlY2lmaWMgKCBUMCYmIG4wLCBjb25zdCB0b190JiwgVDEmJiBuMSwgVERpZmYmJiBuZGlmZiA9IHN0YXRpY19jYXN0PFREaWZmPigxKSApIHsKICAgIHN0ZDo6dmVjdG9yPFQ+IGl0ZW1zOwogICAgaWYgKCBuMCA9PSBuMSB8fCBuZGlmZiA9PSBzdGF0aWNfY2FzdDxURGlmZj4oIDAgKSApCiAgICAgICAgcmV0dXJuIHNldF9idWlsZDxUPiggc3RkOjptb3ZlKCBpdGVtcyApICk7CiAgICAKICAgIFQgYzAgPSBuMDsKICAgIAogICAgaWYgKCBuMCA8IG4xICkgewogICAgICAgIGlmICggbmRpZmYgPCBzdGF0aWNfY2FzdDxURGlmZj4oIDAgKSApCiAgICAgICAgICAgIHJldHVybiBzZXRfYnVpbGQ8VD4oIHN0ZDo6bW92ZSggaXRlbXMgKSApOwogICAgICAgIAogICAgICAgIHdoaWxlICggYzAgPD0gbjEgKSB7CiAgICAgICAgICAgIGl0ZW1zLmVtcGxhY2VfYmFjayggYzAgKTsKICAgICAgICAgICAgYzAgKz0gbmRpZmY7CiAgICAgICAgfQogICAgfQogICAgZWxzZSB7CiAgICAgICAgaWYgKCBuZGlmZiA+IHN0YXRpY19jYXN0PFREaWZmPiggMCApICkKICAgICAgICAgICAgcmV0dXJuIHNldF9idWlsZDxUPiggc3RkOjptb3ZlKCBpdGVtcyApICk7CiAgICAgICAgCiAgICAgICAgd2hpbGUgKCBjMCA+PSBuMSApIHsKICAgICAgICAgICAgaXRlbXMuZW1wbGFjZV9iYWNrKCBjMCApOwogICAgICAgICAgICBjMCArPSBuZGlmZjsKICAgICAgICB9CiAgICB9CiAgICAKICAgIHJldHVybiBzZXRfYnVpbGQ8VD4oIHN0ZDo6bW92ZSggaXRlbXMgKSApOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVDAsIHR5cGVuYW1lIFQxID0gVDA+CnNldF9idWlsZDxUMD4gbWFrZSAoIFQwJiYgbjAsIFQxJiYgbjEgKSB7CiAgICByZXR1cm4gbWFrZV9zcGVjaWZpYzxUMCwgVDAsIFQxPiggc3RkOjpmb3J3YXJkPFQwPiggbjAgKSwgdG8sIHN0ZDo6Zm9yd2FyZDxUMT4oIG4xICkgKTsgCn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUMCwgdHlwZW5hbWUgVDEgPSBUMCwgdHlwZW5hbWUgVERpZmYgPSBkZWNsdHlwZSggc3RkOjpkZWNsdmFsPFQxPigpIC0gc3RkOjpkZWNsdmFsPFQwPigpICk+CnNldF9idWlsZDxUMD4gbWFrZSAoIFQwJiYgbjAsIGNvbnN0IHRvX3QmLCBUMSYmIG4xLCBURGlmZiYmIG5kaWZmID0gc3RhdGljX2Nhc3Q8VERpZmY+KDEpICkgewogICAgcmV0dXJuIG1ha2Vfc3BlY2lmaWM8VDAsIFQwLCBUMSwgVERpZmY+KCBzdGQ6OmZvcndhcmQ8VDA+KCBuMCApLCB0bywgc3RkOjpmb3J3YXJkPFQxPiggbjEgKSwgc3RkOjpmb3J3YXJkPFREaWZmPiggbmRpZmYgKSApOyAKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFQwLCB0eXBlbmFtZSBUMSA9IFQwLCB0eXBlbmFtZSBUTGltID0gVDA+CnNldF9idWlsZDxUPiBtYWtlX3NwZWNpZmljICggVDAmJiBuMCwgVDEmJiBuMSwgY29uc3QgdW50aWxfdCYsIFRMaW0mJiBubGltICkgewogICAgdHlwZWRlZiBkZWNsdHlwZSggc3RkOjpkZWNsdmFsPFQxPigpIC0gc3RkOjpkZWNsdmFsPFQwPigpICkgVERpZmY7CiAgICBURGlmZiBuZGlmZiA9IG4xIC0gbjA7CiAgICByZXR1cm4gbWFrZV9zcGVjaWZpYzxULCBUMCwgVExpbSwgVERpZmY+KCBzdGQ6OmZvcndhcmQ8VDA+KCBuMCApLCB0bywgc3RkOjpmb3J3YXJkPFRMaW0+KCBubGltICksIHN0ZDo6Zm9yd2FyZDxURGlmZj4oIG5kaWZmICkgKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQwLCB0eXBlbmFtZSBUMSA9IFQwLCB0eXBlbmFtZSBUTGltID0gVDA+CnNldF9idWlsZDxUMD4gbWFrZSAoIFQwJiYgbjAsIFQxJiYgbjEsIGNvbnN0IHVudGlsX3QmLCBUTGltJiYgbmxpbSApIHsKICAgIHJldHVybiBtYWtlX3NwZWNpZmljPFQwLCBUMCwgVDEsIFRMaW0+KCBzdGQ6OmZvcndhcmQ8VDA+KCBuMCApLCBzdGQ6OmZvcndhcmQ8VDE+KCBuMSApLCB1bnRpbCwgc3RkOjpmb3J3YXJkPFRMaW0+KCBubGltICkgKTsgCn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUMCwgdHlwZW5hbWUgVDEgPSBUMCwgdHlwZW5hbWUgVExpbSA9IFQwPgpzZXRfYnVpbGQ8VDA+IG1ha2UgKCBUMCYmIG4wLCBUMSYmIG4xLCBUTGltJiYgbmxpbSApIHsKICAgIHJldHVybiBtYWtlX3NwZWNpZmljPFQwLCBUMCwgVDEsIFRMaW0+KCBzdGQ6OmZvcndhcmQ8VDA+KCBuMCApLCBzdGQ6OmZvcndhcmQ8VDE+KCBuMSApLCB1bnRpbCwgc3RkOjpmb3J3YXJkPFRMaW0+KCBubGltICkgKTsgCn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUUmFuZ2U+CnZvaWQgUHJpbnQgKCBUUmFuZ2UmJiByYW5nZSApIHsKICAgIHN0ZDo6Y291dCA8PCAiWyAiOwogICAgZm9yICggYXV0byYgciA6IHJhbmdlICkgewogICAgICAgIHN0ZDo6Y291dCA8PCByIDw8ICcgJzsKICAgIH0KICAgIHN0ZDo6Y291dCA8PCAiXSIgPDwgc3RkOjplbmRsOwp9CgppbnQgbWFpbiAoIGludCBhcmdjLCBjaGFyKiogYXJndiApIHsKCS8vIFdoaWxlIHRoZSBuZXh0IGxpbmUgd291bGQgYmUgdGhlIGlkZWFsIG1hdGgtbGlrZSBzeW50YXgKICAgIC8vIHdlIGNhbid0IGhhdmUgaXQgYmVjYXVzZSBgb3BlcmF0b3J8YCBpcyBsZWZ0LWFzc29jaWF0aXZlCiAgICAvLyB3ZSwgaW5zdGVhZCBvZiB0aGUgYmVsb3cuLi4KICAgIC8vYXV0byByZXN1bHRzID0gWyAoIHggKiB4ICkgfCAoMSwgMjApIHwgKHggKiB4ID4gMTQ0KSBdIDsKICAgIAogICAgLy8gd2Ugc3RhcnQgd2l0aCBhIHJhbmdlIGluc3RlYWQsIHNvIHdlIGNhbiBidWlsZCBpdCB1cCBmcm9tIHRoZXJlCiAgICAvLyBhbHNvLCBpbiBDKysgd2UgdXNlIGxhbWJkYXMKICAgIC8vYXV0byByZXN1bHRzID0gWyBidWlsZCgxLCB0bywgMjApIHwgKCB4ICogeCApIHwgKHggKiB4ID4gMTQ0KSBdIDsKICAgIGF1dG8gcmVzdWx0czEgPSBbXSggaW50IHggKSB7IHJldHVybiB4ICogeDsgfSB8IG1ha2UoIDEsIHRvLCAyMCApICYgW10oIGludCB4ICl7IHJldHVybiB4ICogeCA+IDE0NDsgfTsKICAgIHN0ZDo6Y291dCA8PCAibWFrZSgxLCB0bywgMjApOiIgPDwgc3RkOjplbmRsOwogICAgUHJpbnQoIHJlc3VsdHMxICk7CiAgICAKICAgIGF1dG8gcmVzdWx0czIgPSBbXSggaW50IHggKSB7IHJldHVybiB4ICogeDsgfSB8IG1ha2UoIDEsIDIsIDIwICkgJiBbXSggaW50IHggKXsgcmV0dXJuIHggKiB4ID4gMTQ0OyB9OwogICAgc3RkOjpjb3V0IDw8ICJtYWtlKDEsIDIsIDIwKToiIDw8IHN0ZDo6ZW5kbDsKICAgIFByaW50KCByZXN1bHRzMiApOwogICAgCiAgICBhdXRvIHJlc3VsdHMzID0gW10oIGludCB4ICkgeyByZXR1cm4geCAqIHg7IH0gfCBtYWtlKCAxLCA0LCAyMCApICYgW10oIGludCB4ICl7IHJldHVybiB4ICogeCA+IDE0NDsgfTsKICAgIHN0ZDo6Y291dCA8PCAibWFrZSgxLCA0LCAyMCk6IiA8PCBzdGQ6OmVuZGw7CiAgICBQcmludCggcmVzdWx0czMgKTsKICAgIAp9