Walletfox.com

Range-v3 - practical examples


using namespace ranges;
auto const v = {1u,1u,1u,0u}; 
auto v_rev = v | view::reverse; // [0,1,1,1]
auto v_bin = view::generate([n = 1u] () mutable {return (n <<= 1u) >> 1u;}); // [1,2,4,8...]
auto val = inner_product(v_rev, v_bin, 0u); // 0*1+1*2+1*4+1*8 = 14
using namespace ranges;
auto s = std::string{"feel_the_force"};
auto words = s | view::split('_'); // [[f,e,e,l],[t,h,e],[f,o,r,c,e]]
auto words_cap = words | view::transform([](auto w){
    auto head = w | view::take(1) 
                  | view::transform([](unsigned char c){return std::toupper(c);}); // e.g. [F]
    return view::concat(head, w | view::tail); // e.g. [F,e,e,l]
}); // [[F,e,e,l],[T,h,e],[F,o,r,c,e]]
std::string s_camelcase = words_cap | view::join; // FeelTheForce
using namespace ranges;
auto rng = view::generate(
                [p = std::pair{0,1}] () mutable { 
                          auto [a0,b0] = p;
                          p = {b0, a0 + b0};
                          return a0;
                }); 
auto fib10 = rng | view::take(10); // [0,1,1,2,3,5,8,13,21,34]

Note: Single words only.

using namespace ranges;
auto shift = 11;
auto s = std::string {"apple"};       

auto alphabet = view::closed_iota('a','z') | view::cycle; // [a,b,c...a,b,c...]
auto shifted_alphabet = alphabet | view::drop(shift); // [l,m,n...a,b,c...]

auto encrypted = s | view::for_each([shifted_alphabet](char letter){
        return shifted_alphabet | view::drop(letter - 'a') | view::take(1); 
}); // [l,a,a,w,p]

Explanation: view::for_each processes every letter of the word "apple". For example, for the letter 'e' we drop ('e'-'a') = (101 - 97) = 4 characters from the shifted alphabet. This means that [l,m,n...] becomes [p,q,r...]. To get the new letter 'e' we take the first letter of the transformed sequence, i.e. 'p'.

Note: This is the equivalent of ranges::inner_product.

using namespace ranges;
auto dotProduct = [](const auto& v1, const auto& v2){
                               return accumulate(
                                         view::zip_with(std::multiplies<>(), v1,v2), 0.0);};
    
auto v1 = {1,2,3};
auto v2 = {4,5,6};
std::cout << dotProduct(v1,v2); // 32

Note: This is the equivalent of nested for loops.

using namespace ranges;
auto const v = std::vector {'a', 'b', 'c'}; 
auto rng = view::cartesian_product(v,v,v);
for(auto [x,y,z] : rng)
    std::cout << x << ' ' << y <<  ' ' << z << '\n';
// 27 permutations with repetition
// a a a
// a a b
// a a c
// a b a
// a b b
// ...

Note: Sort the sequence first.

auto s = std::string{"cab"};
ranges::sort(s);
do {
    std::cout << s << '\n';
} while (ranges::next_permutation(s));
// abc
// acb
// bac
// bca
// cab
// cba

using namespace ranges;
auto v = {0.5,0.25,0.125,0.125};
auto v_p_logp =  v | view::transform([](auto p){return -p*std::log2(p);});
auto val = accumulate(v_p_logp, 0.0); // 1.75

using namespace ranges;
auto v_ints = view::iota(1); // [1,2,3,4,5,6,7,8...]
auto v_triseq = v_ints | view::transform([](int n){return n*(n+1)/2;}); // [1,3,6,10,15,21,28...]
auto v_first5 = v_triseq | view::take(5); // [1,3,6,10,15]

Note: Midpoint Riemann integral.

using namespace ranges;
auto steps = 5;
auto a = 0.0;
auto b = 2.0;
auto dx = (b-a)/steps; // 0.4
    
auto area = 
   dx * accumulate(
      // generates [0.2, 0.6, 1, 1.4, 1.8]
      view::generate_n([a,dx,i = 0] () mutable {return a + dx*(0.5 + i++);}, steps) |
      // generates pow3 [0.008, 0.216, 1, 2.744, 5.832]
      view::transform([](auto x){return x*x*x;}),
      0.0); // 0.4*(0.008 + 0.216 + 1 + 2.744 + 5.832) = 3.92

Tagged: Range-v3