// A few common random functions. (1.03)

#include <algorithm>
#include <experimental/iterator>
#include <random>
#include <iostream>
using namespace std;

// Initialize generator with non-deterministic seed.

static thread_local default_random_engine re_(random_device{}());

// Real in the range [0, 1).

double randreal()
{
    uniform_real_distribution<double> pick(0, 1);
    return pick(re_);
}

// Integer in the range [lo, hi].

int randint(int lo, int hi)
{
    uniform_int_distribution<> pick(lo, hi);
    return pick(re_);
}

// Boolean where probability of true is p and false is (1-p).

bool randbool(double p)
{
    bernoulli_distribution pick(p);
    return pick(re_);
}

// Main.

template<typename Func, typename... Args>
void display(int n, Func f, Args... args)
{
    cout << '[';
    generate_n(experimental::make_ostream_joiner(cout, ", "), n,
               [=]{ return f(args...); });
    cout << "]\n";
}

int main()
{
    display(10, randreal);
    display(10, randint, -5, 5);
    display(10, randbool, 0.5);
}