Note
BubbleRand: a deliberately lazy sampler
A goofy idea for when you want "kinda random," not cryptographic or even fair.
The premise is simple: take a distribution (an array of numbers), randomly bubble sort small sections a handful of times, then grab the middle value. BubbleRand is intentionally slow, intentionally biased, and perfect for gamey chaos.
Think of it as "analog randomness." You can tune how many passes you do, how wide the subranges are, and how many swaps you allow per pass.
BubbleRand in motion
The box highlights a random slice that gets bubble-sorted in a random direction. After a few passes, we grab the middle value as the output.
- #10.12
- #20.83
- #30.47
- #40.65
- #50.29
- #60.91
- #70.54
- #80.06
- #90.78
- #100.33
- #110.71
- #120.18
- #130.59
- #140.25
- #150.88
Quick randomness check
I ran a small comparison (20000 samples, 30 bins) between Math.random, crypto randomness, and BubbleRand. The charts below show the histogram distribution and a few simple stats.
Math.random
crypto.getRandomValues
BubbleRand (Math.random)
Notes: BubbleRand randomizes sort direction per pass. Chi-square is relative to a uniform distribution (lower is closer to uniform). Generated 2026-01-29.
How to read the numbers
These are simple smoke tests, not cryptographic validation. For serious randomness, use dedicated suites (Dieharder, TestU01) and much larger sample sizes.
Algorithm sketch
- Start with a numeric distribution array.
- Pick a random slice window (start + length).
- Bubble-sort only that slice, but cap the swaps.
- Repeat 10 times (or any number you like).
- Return the middle value of the entire array.
Pseudo-code
function bubbleRand(values, passes = 10) {
const arr = values.slice()
for (let i = 0; i < passes; i++) {
const start = randInt(0, arr.length - 2)
const len = randInt(2, Math.min(12, arr.length - start))
const end = start + len
bubbleSlice(arr, start, end, maxSwaps = len * 2)
}
return arr[Math.floor(arr.length / 2)]
}Why bother?
It's not about correctness. It's about texture. Think of loot tables, ambient behaviors, or procedural variation that should feel "alive" but not purely random.