Ch12.7: Real-World Examples

Example 1: Password Generator

This example generates random passwords with lengths between 12 and 20 characters, using alphanumeric characters (0-9, a-z, A-Z). It demonstrates using multiple distributions and mapping random values to character sets.

Source: examples/0014.random/password.cc


#include <fast_io.h>
#include <fast_io_device.h>
#include <random>

using namespace fast_io::io;

int main(int argc, char **argv)
{
    ::std::size_t n{100};
    if (1 < argc)
    {
        n = fast_io::to<::std::size_t>(fast_io::mnp::os_c_str(argv[1]));
    }

    fast_io::u8obuf_file obf(u"password.txt");
    fast_io::ibuf_white_hole_engine eng;

    // Distribution for character selection (0-61 maps to 62 characters)
    ::std::uniform_int_distribution<::std::size_t> ud(0, 61);

    // Distribution for password length (12-20 characters)
    ::std::uniform_int_distribution<::std::size_t> rlen(12, 20);

    for (::std::size_t i{}; i != n; ++i)
    {
        // Generate a password of random length
        for (::std::size_t j{}, s(rlen(eng)); j != s; ++j)
        {
            char8_t ch(static_cast<char8_t>(ud(eng)));

            // Map 0-9 to '0'-'9'
            if (ch < 10u)
            {
                ch += u8'0';
            }
            // Map 10-35 to 'a'-'z'
            else if (ch < 36u)
            {
                ch = ch - 10u + u8'a';
            }
            // Map 36-61 to 'A'-'Z'
            else
            {
                ch = ch - 36u + u8'A';
            }

            print(obf, fast_io::mnp::chvw(ch));
        }
        println(obf);
    }
}

Key points:

WasmPass PWA: Use the Password Generator in Your Browser

The password generator example from this chapter has been compiled to WebAssembly and is available as a Progressive Web App (PWA) called WasmPass. You can use it directly in your browser without installing anything!

Try it now: https://wasmpass.pages.dev/

As a PWA, WasmPass can be installed on your device and works offline. It uses the same cryptographically secure random number generation as the C++ example, powered by fast_io's ibuf_white_hole_engine.

Example 2: Birth Simulation with Bernoulli Distribution

This example simulates a scenario where parents keep having children until they have a boy. It uses the natural male-to-female birth ratio (approximately 1.03:1) and demonstrates the bernoulli_distribution for modeling binary outcomes with a given probability.

Source: examples/0014.random/stop_born_child_until_boy.cc


#include <random>
#include <fast_io.h>
#include <map>

using namespace fast_io::io;

int main(int argc, char **argv)
{
    using namespace fast_io::mnp;

    if (argc < 2)
    {
        if (argc == 0)
        {
            return 1;
        }
        perr("Usage: ", os_c_str(*argv), " N\n");
        return 1;
    }

    // Natural male-to-female ratio is approximately 1.03:1
    constexpr auto natural_male_to_female_ratio{1.03};
    constexpr auto total_ratio{natural_male_to_female_ratio + 1.0};
    constexpr auto male_probability{natural_male_to_female_ratio / total_ratio};

    fast_io::ibuf_white_hole_engine engine;

    // Bernoulli distribution with probability of male birth
    ::std::bernoulli_distribution dis(male_probability);

    ::std::uint_least64_t const n{::fast_io::to<::std::uint_least64_t>(os_c_str(argv[1]))};
    ::std::map<::std::uint_least64_t, ::std::uint_least64_t> map;
    ::std::uint_least64_t total_population{};

    // Simulate n families
    for (::std::uint_least64_t i{}; i != n; ++i)
    {
        ::std::uint_least64_t j{1};

        // Keep having children until a boy is born
        for (; !dis(engine); ++j)
            ;

        ++map[j];
        total_population += j;
    }

    fast_io::out_buf_type obf(fast_io::out());

    // Print distribution of family sizes
    for (auto const &e : map)
    {
        print(obf, e.first, " ", e.second, " (",
              percentage_conventional(e.second, n), ")\n");
    }

    ::std::uint_least64_t const females{total_population - n};
    println(obf, "males:", n, "\tfemales:", females,
            "\n"
            "total population:",
            total_population,
            "\n"
            "Sex Ratio:",
            percentage_sex_ratio(n, females));
}

Key points:

Running the Examples

To compile and run these examples:


# Compile password generator
g++ -std=c++20 -O2 -o password password.cc -I/path/to/fast_io/include

# Generate 50 passwords
./password 50

# Compile birth simulation
g++ -std=c++20 -O2 -o birth_sim stop_born_child_until_boy.cc -I/path/to/fast_io/include

# Simulate 10000 families
./birth_sim 10000

Sample Output from Birth Simulation

Here's what the birth simulation outputs when run with 100 million families:


$ ./stop_born_child_until_boy 100000000
1 50741327 (50.74%)
2 24990841 (24.99%)
3 12313210 (12.31%)
4 6063416 (6.06%)
5 2990841 (2.99%)
6 1471025 (1.47%)
7 725002 (0.73%)
8 357182 (0.36%)
9 175727 (0.18%)
10 86761 (0.09%)
11 43036 (0.04%)
12 21090 (0.02%)
13 10381 (0.01%)
14 5167 (0.01%)
15 2548 (0.00%)
16 1258 (0.00%)
17 607 (0.00%)
18 303 (0.00%)
19 136 (0.00%)
20 77 (0.00%)
21 32 (0.00%)
22 18 (0.00%)
23 10 (0.00%)
24 3 (0.00%)
25 1 (0.00%)
29 1 (0.00%)
males:100000000    females:97091717
total population:197091717
Sex Ratio:103.00:100

Key insight: Notice that some families have many girls before having a boy. In this simulation, one family had their first boy as the 29th child! This is not a genetic defect — it's simply probability. With 100 million families, it's statistically expected that some families will have long streaks of girls.

Even at the 10th child, we see 86,761 families (0.09%) that had 9 girls before finally having a boy. This is completely normal and expected from the laws of probability. Each birth is an independent event with approximately 50.7% chance of being male.

Mathematical proof: See Ch12.8.1: Mathematical Proof for a complete mathematical proof of why this stopping rule doesn't affect the sex ratio at birth.

Percentage Manipulators Reference

The examples above use several percentage-related manipulators from fast_io::mnp. Here's a complete reference:

Manipulator Description Example Output
percentage_conventional(num, den) Calculates num/den * 100 and formats as percentage with 2 decimal places percentage_conventional(1, 4)25.00%
comma_percentage_conventional(num, den) Same as above, but uses comma as decimal separator comma_percentage_conventional(1, 4)25,00%
percentage_sex_ratio(male, female) Calculates male-to-female ratio as X.XX:100 format (males per 100 females) percentage_sex_ratio(103, 100)103.00:100
comma_percentage_sex_ratio(male, female) Same as above, but uses comma as decimal separator comma_percentage_sex_ratio(103, 100)103,00:100
base_percentage_conventional<base>(num, den) Percentage in different base (2-36) base_percentage_conventional<16>(1, 4)19.00%
base_percentage_sex_ratio<base>(male, female) Sex ratio in different base (2-36) base_percentage_sex_ratio<16>(103, 100)67.00:100

Template parameters: All manipulators accept optional template parameters: <uppercase, full, showpos> to control formatting.

Key Takeaways