Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 11302x 11302x 11302x 2x 2x 2x 2x 2x 2x 224615x 224615x 224615x 224615x 224615x 224615x 2x 2x 2x 2x 2x 107411x 107411x 2x 2x 2x 2x 2x 720x 720x 2x 2x 2x 2x 2x 2x 311x 27638x 27638x 27638x 311x 311x 2x 2x 2x 2x 2x 4531x 4531x 4531x 2x 2x 2x 2x 2x 243x 243x 243x 243x 243x 2x 2x 2x 2x 2x 148x 148x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 18x 18x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 9908x 9908x 9908x 311360x 311360x 311360x 9908x 9908x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 2x 2x 2x 2x 2x 2x 2x 2x | /**
* Seeded Random Number Generator
*
* Uses the Mulberry32 algorithm - a fast, high-quality 32-bit PRNG.
* This provides deterministic randomness for reproducible test runs.
*/
/**
* Mulberry32 PRNG - fast, good distribution, seedable
*/
export class SeededRandom {
private state: number
constructor(seed: number) {
// Ensure seed is a 32-bit integer
this.state = seed >>> 0
}
/**
* Returns a float in [0, 1)
* Uses the Mulberry32 algorithm
*/
next(): number {
// Mulberry32 algorithm
let t = (this.state += 0x6d2b79f5)
t = Math.imul(t ^ (t >>> 15), t | 1)
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
/**
* Returns an integer in [min, max] inclusive
*/
nextInt(min: number, max: number): number {
return Math.floor(this.next() * (max - min + 1)) + min
}
/**
* Returns true with probability p
*/
chance(p: number): boolean {
return this.next() < p
}
/**
* Shuffle an array in place using Fisher-Yates
* Returns the same array for chaining
*/
shuffle<T>(array: T[]): T[] {
for (let i = array.length - 1; i > 0; i--) {
const j = this.nextInt(0, i)
;[array[i], array[j]] = [array[j], array[i]]
}
return array
}
/**
* Pick a random element from an array
*/
pick<T>(array: T[]): T {
if (array.length === 0) {
throw new Error('Cannot pick from empty array')
}
return array[this.nextInt(0, array.length - 1)]
}
/**
* Pick n random elements from an array (without replacement)
*/
pickN<T>(array: T[], n: number): T[] {
if (n > array.length) {
throw new Error(`Cannot pick ${n} elements from array of length ${array.length}`)
}
const copy = [...array]
this.shuffle(copy)
return copy.slice(0, n)
}
/**
* Returns a random float in [min, max)
*/
nextFloat(min: number, max: number): number {
return this.next() * (max - min) + min
}
/**
* Returns a normally distributed random number using Box-Muller transform
* @param mean - The mean of the distribution
* @param stdDev - The standard deviation
*/
nextGaussian(mean = 0, stdDev = 1): number {
// Box-Muller transform
const u1 = this.next()
const u2 = this.next()
const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)
return z0 * stdDev + mean
}
/**
* Create a Math.random() replacement function that uses this RNG.
* Used to mock Math.random during test execution.
*/
createMathRandomMock(): () => number {
return () => this.next()
}
/**
* Get the current state (for debugging/serialization)
*/
getState(): number {
return this.state
}
/**
* Create a new SeededRandom with a derived seed
* Useful for creating independent streams from a parent RNG
*/
derive(label: string): SeededRandom {
// Use a simple hash to derive a new seed from label
let hash = this.state
for (let i = 0; i < label.length; i++) {
hash = Math.imul(hash ^ label.charCodeAt(i), 0x5bd1e995)
hash ^= hash >>> 15
}
return new SeededRandom(hash >>> 0)
}
}
/**
* Mock Math.random with a seeded version during a function execution.
* Automatically restores the original Math.random after completion.
*
* @param seed - The seed for the RNG
* @param fn - The function to execute with mocked Math.random
* @returns The result of fn
*/
export function withSeededRandom<T>(seed: number, fn: () => T): T {
const originalRandom = Math.random
const rng = new SeededRandom(seed)
Math.random = rng.createMathRandomMock()
try {
return fn()
} finally {
Math.random = originalRandom
}
}
/**
* Async version of withSeededRandom for async functions.
*
* @param seed - The seed for the RNG
* @param fn - The async function to execute with mocked Math.random
* @returns The result of fn
*/
export async function withSeededRandomAsync<T>(seed: number, fn: () => Promise<T>): Promise<T> {
const originalRandom = Math.random
const rng = new SeededRandom(seed)
Math.random = rng.createMathRandomMock()
try {
return await fn()
} finally {
Math.random = originalRandom
}
}
|