summaryrefslogtreecommitdiff
path: root/bin/random-id.ts
blob: b8bf364111bd057edced7c22c151fb03e0a5bdec (plain)
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());
}