Math
Hashes and buckets
A sorting table: keys as paper tags, a carriage that hashes each one and drops it into the bin its hash names, a collision as two different keys in one bin. The hash is a named function - the sum of the codes, the base-31 polynomial, FNV-1a - or the uniform oracle behind the birthday curve. Edit a key, watch its hash computed character by character, flip one bit and count the hash bits that move; compare two functions on the same keys.

What happens
Twenty-three people in a room share a birthday more often than not, and the same arithmetic sizes a hash table. Here the keys are real strings and the hash is a NAMED function: the sum of the character codes, the polynomial with base 31, FNV-1a - or the uniform oracle, which has no key at all and is the model behind the curve. A carriage on the rail hashes each tag and drops it into the bin its index names; a tag landing on another is a collision, and both keys stay lit. The sheet computes the probe's hash character by character, flips one bit of the key and counts the hash bits that move. Three questions are kept apart: collisions, uniformity (chi-square of the loads against n/m, expected m − 1) and the avalanche; a histogram that looks uniform on random words is not a verdict on the function - feed the sum of the letters a list of anagrams and every key lands in one bin. None of this is cryptographic strength.
Equations used in the module
Equations n keys into m buckets, uniformly P(at least one collision) = 1 − prod (1 − i/m), EXACTLY: n = 23, m = 365 -> 0.50729723432398566; n = 50 -> 0.97037357957798842 expected empty buckets = m·(1 − 1/m)^n EXACTLY - not the usual m·e^(−n/m): at n = m = 100 they are 36.603234127322921 and 36.787944, and the difference is visible keys until the first collision, on average: sqrt(pi·m/2) + 2/3 = 24.611199639354552 for m = 365 (counted 24.6767 over 20 000 runs) maximum load at n = m behaves like ln n / ln ln n - an ASYMPTOTIC, not a formula: the measured ratio GROWS, 1.32 at m = 64, 1.49 at 256, 1.55 at 1024 so it is checked as a bracket and as a monotone trend, never pinned to a number measured against the exact curve (20 000 runs each): n = 10 -> 0.11605 against 0.11695; n = 23 -> 0.50800 against 0.50730; n = 70 -> 0.99920 against 0.99916 named functions on a key k = c₁c₂…c_n (character codes), all modulo 2³²: sum: h = Σ c_i; base 31: h ← 31·h + c_i; FNV-1a: h₀ = 2166136261, h ← (h xor c_i)·16777619 bin = h mod m; the uniform oracle draws the bin from the seed and the key's NUMBER - it has no key uniformity: χ² = Σ (load_j − n/m)² / (n/m) over the m bins; a uniform deal gives m − 1 ± √(2(m − 1)) avalanche: mean over the keys of Hamming(h(k), h(k′)) with ONE bit of k flipped; an ideal function moves 16 of 32 measured (seed 20260913, 40 random words into 64 bins): FNV-1a 7 collisions, χ² 46.4, avalanche 14.6; base 31: 9, 52.8, 6.2; sum: 8, 52.8, 2.05; oracle: 9, 59.2, no bits 40 anagrams of one word under the sum: 39 collisions, one chain of 40, χ² = 2520 - the sum cannot tell the order of the letters


