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:
- Uses two distributions: one for character selection, one for password length.
- Maps the uniform distribution [0, 61] to character ranges (digits, lowercase, uppercase).
- Each password has a random length between 12 and 20 characters.
-
Uses
ibuf_white_hole_enginefor cryptographically secure randomness.
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:
-
Uses
bernoulli_distributionwith probability ≈ 0.507 (natural male birth rate). - Simulates families having children until a boy is born.
- Tracks how many children each family has and computes statistics.
- Demonstrates using distributions for statistical simulations.
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
- Real-world applications often combine multiple distributions (uniform for selection, uniform for size, Bernoulli for binary outcomes).
-
ibuf_white_hole_engineprovides cryptographically secure randomness suitable for password generation. -
Distributions like
bernoulli_distributionmake it easy to model probabilistic events with specific probabilities. - Mapping uniform distributions to character sets is a common pattern in password generators.
- Statistical simulations benefit from using the correct distribution rather than manual transformations.
- Sex ratio misconception: The simulation above demonstrates that even if every family keeps having children until they get a boy, the overall sex ratio at birth remains at the natural ratio (approximately 103:100 male-to-female). This is a common misunderstanding — stopping rules do not affect the underlying probability. In large samples, the ratio will always converge to the natural biological ratio. The only real-world causes of skewed sex ratios are sex-selective abortion, female infanticide, and other sex-selective technologies, not family planning decisions.
- Late boys are just probability: The sample output shows that some families have their first boy as the 10th, 15th, or even 29th child. This is not a genetic defect — it's simply the laws of probability. With a large enough population, it's statistically expected that some families will have long streaks of girls. Each birth is an independent event, and "unlucky" streaks are a natural consequence of randomness.