1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#!/usr/bin/env node --disable-warning=DEP0180 --no-warnings
const idChars = (function (): string[] {
const chars: string[] = [];
function code(x: string | number): number {
return typeof x === "string" ? x.charCodeAt(0) : x;
}
function add(from: string | number, to: string | number): void {
const fromCode = code(from);
const toCode = code(to);
for (let c = fromCode; c <= toCode; ++c) {
chars.push(String.fromCharCode(c));
}
}
add("0", "9");
add("a", "z");
add("A", "Z");
return chars;
})();
/*
Alphabet size: 62 characters (A–Z, a–z, 0–9)
Total possible IDs of length n: TOTAL_IDS = 62^n
To compute the probability that two randomly generated IDs collide (i.e., are identical): P_COLLISION = 1 / TOTAL_IDS
==========================================================
ID Length | ID space | P(Collision) | Intuition
-----------|----------------|----------------|------------
5 | 916,132,832 | ~1.09 × 10⁻⁹ | ~1 in a billion (like lottery odds)
6 | 56,800,235,584 | ~1.76 × 10⁻¹¹ | ~1 in 50 billion (world population × 6)
17 | 2.96 × 10³⁰ | ~3.38 × 10⁻³¹ | ~1 in a nonillion (grains of sand × 10¹⁹)
==========================================================
Interpretation:
- At **length 5**, collisions are rare but not implausible if generating millions of IDs.
- At **length 6**, collisions are extremely rare - safe for most casual uses.
- At **length 17**, collisions are cosmically unlikely—about as probable as picking the same atom out of all atoms in the solar system.
==========================================================
== Out of a pool of 100,000 ===
Alphabet size: 62 characters (A–Z, a–z, 0–9)
Existing IDs: N = 100 000
Formulas:
TOTAL_IDS(n) = 62^n
P_match_one = 1 / TOTAL_IDS(n)
P_collision_any = 1 − (1 − P_match_one)^N
--------------------------------------------------------------------------------
n | TOTAL_IDS(n) | P_collision_any | Intuition
---+----------------------+--------------------------------+-------------------------------------------
5 | 62^5 = 916 132 832 | 1 − (1 − 1/916 132 832)^100 000
| | ≈ 1.09 × 10⁻⁴ | ~0.01% → ~1 in 9 200
| | | (about as rare as drawing the same
| | | lottery number in ~9 200 draws)
6 | 62^6 = 56 800 235 584| ≈ 1.76 × 10⁻⁶ | ~0.000176% → ~1 in 568 000
| | | (like finding a specific LEGO
| | | brick in a pile of half a million)
8 | 62^8 ≈ 2.18 × 10^14 | ≈ 4.58 × 10⁻¹⁰ | ~4.6 × 10⁻⁸% → ~1 in 2.2 billion
| | | (on par with winning a major lottery)
17 | 62^17 ≈ 2.96 × 10^30 | ≈ 3.38 × 10⁻²⁶ | ~3.4 × 10⁻²⁴% → ~1 in 3 × 10^25
| | | (effectively zero—astronomically
| | | unlikely, far beyond grains of sand
| | | on every beach on Earth)
--------------------------------------------------------------------------------
Reasoning:
- TOTAL_IDS(n) counts all possible length-n strings.
- P_match_one = chance it matches one given ID.
- With N existing, P_collision_any = 1 minus the chance it misses all N.
- For n=5 collisions are possible if you generate many IDs; for n≥8 they're vanishingly rare; for n=17 they're effectively impossible in any realistic system.
*/
// With 62 possible chars, a 17 char long ID has about 10^30 possible values,
// the chance of finding any of 8 billion of them is about the same as the
// chance of finding a single specific grain of sand in on earth.
//
const idLength = process.env.ID_LENGTH ? parseInt(process.env.ID_LENGTH) :17;
function randomId(length: number = idLength): string {
const chars: string[] = [];
for (let i = 0; i < length; ++i) {
const c = Math.floor(Math.random() * idChars.length);
chars.push(idChars[c]!);
}
return chars.join("");
}
// take count from from first argument, default to 1
const count = parseInt(process.argv[2] || "1");
// execute and print
for (let i = 0; i < count; ++i) {
console.log(randomId());
}
|