Skip to content

Commit 2748341

Browse files
authored
Merge pull request #10 from MXASoundNDEv/codex/add-fisher-yates-shuffle-algorithm-with-tests
Add Fisher-Yates shuffle algorithm
2 parents 0a72e12 + 8587e62 commit 2748341

File tree

6 files changed

+77
-4
lines changed

6 files changed

+77
-4
lines changed

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![npm version](https://img.shields.io/npm/v/algorith)](https://www.npmjs.com/package/algorith)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5-
[![Tests](https://img.shields.io/badge/tests-114%20passing-brightgreen)](./test/)
5+
[![Tests](https://img.shields.io/badge/tests-115%20passing-brightgreen)](./test/)
66

77
> Collection complète d'algorithmes de similarité textuelle et moteur de génération aléatoire avancé
88
@@ -21,7 +21,8 @@ const {
2121
hamming,
2222
compareAll,
2323
RandomEngine,
24-
AutocompleteEngine
24+
AutocompleteEngine,
25+
fisherYatesShuffle
2526
} = require('algorith');
2627

2728
// Comparaison de similarité
@@ -53,6 +54,11 @@ console.log(rng.randomWord()); // "bakaru"
5354
const autocomplete = new AutocompleteEngine({ language: 'fr' });
5455
autocomplete.addWords(['javascript', 'java', 'python']);
5556
console.log(autocomplete.autocomplete('java')); // ['java', 'javascript']
57+
58+
// Mélange Fisher-Yates
59+
const numbers = [1, 2, 3, 4, 5];
60+
const shuffled = fisherYatesShuffle(numbers);
61+
console.log(shuffled); // [3, 1, 5, 2, 4]
5662
```
5763

5864
## 📚 API Documentation
@@ -514,6 +520,20 @@ rng.fade(0.5); // Fonction de lissage
514520
rng.lerp(0, 10, 0.5); // Interpolation linéaire → 5
515521
```
516522

523+
### 🔀 Mélange Fisher-Yates
524+
525+
Mélange un tableau en utilisant l'algorithme de Fisher-Yates.
526+
527+
```javascript
528+
const { fisherYatesShuffle } = require('algorith');
529+
530+
const items = ['a', 'b', 'c', 'd'];
531+
const shuffled = fisherYatesShuffle(items);
532+
533+
console.log(items); // ['a', 'b', 'c', 'd'] (non modifié)
534+
console.log(shuffled); // Mélange aléatoire
535+
```
536+
517537
## 🎯 Exemples d'Usage
518538

519539
### Détection de Doublons
@@ -607,7 +627,7 @@ const map = generateTerrain(100, 100);
607627

608628
## 🧪 Tests
609629

610-
Le module inclut 114 tests complets :
630+
Le module inclut 115 tests complets :
611631

612632
```bash
613633
# Exécuter tous les tests

algorithms/fisherYatesShuffle.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module.exports = function fisherYatesShuffle(array, random = Math.random) {
2+
const result = array.slice();
3+
4+
for (let i = result.length - 1; i > 0; i--) {
5+
const j = Math.floor(random() * (i + 1));
6+
[result[i], result[j]] = [result[j], result[i]];
7+
}
8+
9+
return result;
10+
};

index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ export function diceCoefficient(a: string, b: string): number;
8282
*/
8383
export function trigramScore(a: string, b: string): number;
8484

85+
/**
86+
* Shuffles an array using the Fisher-Yates algorithm
87+
* @param array Input array
88+
* @param random Optional random generator (default: Math.random)
89+
* @returns New shuffled array
90+
*/
91+
export function fisherYatesShuffle<T>(array: T[], random?: () => number): T[];
92+
8593
/**
8694
* Generates the Soundex code for a string with multilingual support
8795
* @param s Input string

index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const cosineSimilarity = require('./algorithms/cosineSimilarity');
99
const soundex = require('./algorithms/soundex');
1010
const RandomEngine = require('./algorithms/RandomEngine');
1111
const AutocompleteEngine = require('./algorithms/autocomplete');
12+
const fisherYatesShuffle = require('./algorithms/fisherYatesShuffle');
1213

1314
function compareAll(a, b) {
1415
return {
@@ -35,5 +36,6 @@ module.exports = {
3536
soundex,
3637
RandomEngine,
3738
AutocompleteEngine,
39+
fisherYatesShuffle,
3840
compareAll
39-
};
41+
};

test/compareAll.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe('Compare All Algorithms', () => {
1212
assert(typeof algorithms.jaro === 'function');
1313
assert(typeof algorithms.cosineSimilarity === 'function');
1414
assert(typeof algorithms.RandomEngine === 'function'); // Constructor
15+
assert(typeof algorithms.fisherYatesShuffle === 'function');
1516
assert(typeof algorithms.compareAll === 'function');
1617
});
1718

test/fisherYatesShuffle.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const assert = require('assert');
2+
const fisherYatesShuffle = require('../algorithms/fisherYatesShuffle');
3+
4+
describe('Fisher-Yates Shuffle', () => {
5+
it('should return a new array without mutating the original', () => {
6+
const original = [1, 2, 3, 4];
7+
const shuffled = fisherYatesShuffle(original, () => 0);
8+
9+
assert.deepStrictEqual(original, [1, 2, 3, 4]);
10+
assert.notStrictEqual(shuffled, original);
11+
});
12+
13+
it('should keep the same elements', () => {
14+
const original = [1, 2, 3, 4, 5];
15+
const shuffled = fisherYatesShuffle(original, () => 0.5);
16+
17+
assert.deepStrictEqual(shuffled.slice().sort((a, b) => a - b), original);
18+
});
19+
20+
it('should produce deterministic output with a custom RNG', () => {
21+
const values = [0.1, 0.7, 0.3];
22+
let index = 0;
23+
const rng = () => values[index++];
24+
25+
const result = fisherYatesShuffle([1, 2, 3, 4], rng);
26+
assert.deepStrictEqual(result, [2, 4, 3, 1]);
27+
});
28+
29+
it('should handle empty arrays', () => {
30+
assert.deepStrictEqual(fisherYatesShuffle([], () => 0.5), []);
31+
});
32+
});

0 commit comments

Comments
 (0)