chore: code improvement for arrayShuffle

This commit is contained in:
Peter Sanderson
2024-10-14 14:14:24 +02:00
committed by Peter Sanderson
parent c56f065475
commit b52bfba948
2 changed files with 14 additions and 6 deletions

View File

@@ -1,8 +1,11 @@
/**
* Randomly shuffles the elements in an array. This method
* does not mutate the original array.
* Implementation of the Fisher-Yates shuffle algorithm.
* The algorithm produces an unbiased permutation: every permutation is equally likely.
* @link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
*
* This method does not mutate the original array.
*/
export const arrayShuffle = <T>(array: readonly T[]) => {
export const arrayShuffle = <T>(array: readonly T[]): T[] => {
const shuffled = array.slice();
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));

View File

@@ -5,19 +5,24 @@ const SAMPLES = 10000;
const TOLERANCE = 0.1;
const EXPECTED = SAMPLES / KEYS.length;
describe('arrayShuffle', () => {
const LOWER_BOUND = (1 - TOLERANCE) * EXPECTED;
const UPPER_BOUND = (1 + TOLERANCE) * EXPECTED;
describe(arrayShuffle.name, () => {
it('shuffles randomly', () => {
const samples = Object.fromEntries(KEYS.map(key => [key, new Array(KEYS.length).fill(0)]));
for (let sample = 0; sample < SAMPLES; ++sample) {
const shuffled = arrayShuffle(KEYS);
for (let i = 0; i < shuffled.length; ++i) {
samples[shuffled[i]][i]++;
}
}
KEYS.forEach(key =>
samples[key].forEach(count => {
expect(count).toBeGreaterThanOrEqual((1 - TOLERANCE) * EXPECTED);
expect(count).toBeLessThanOrEqual((1 + TOLERANCE) * EXPECTED);
expect(count).toBeGreaterThanOrEqual(LOWER_BOUND);
expect(count).toBeLessThanOrEqual(UPPER_BOUND);
}),
);
});