Skip to content

Commit 00e9bc4

Browse files
authored
Add recursive shuffling algorithm (#519)
1 parent 99bc144 commit 00e9bc4

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Algorithms.Shufflers;
2+
using Algorithms.Tests.Helpers;
3+
using FluentAssertions;
4+
using NUnit.Framework;
5+
using System;
6+
7+
namespace Algorithms.Tests.Shufflers
8+
{
9+
public static class RecursiveShufflerTests
10+
{
11+
[Test]
12+
public static void ArrayShuffled_NewArraySameSize(
13+
[Random(10, 1000, 100, Distinct = true)]
14+
int n)
15+
{
16+
// Arrange
17+
var shuffler = new RecursiveShuffler<int>();
18+
var (correctArray, testArray) = RandomHelper.GetArrays(n);
19+
20+
// Act
21+
shuffler.Shuffle(testArray);
22+
23+
// Assert
24+
testArray.Length.Should().Be(correctArray.Length);
25+
}
26+
27+
[Test]
28+
public static void ArrayShuffled_NewArraySameValues(
29+
[Random(10, 1000, 100, Distinct = true)]
30+
int n)
31+
{
32+
// Arrange
33+
var shuffler = new RecursiveShuffler<int>();
34+
var (correctArray, testArray) = RandomHelper.GetArrays(n);
35+
36+
// Act
37+
shuffler.Shuffle(testArray);
38+
39+
// Assert
40+
testArray.Should().BeEquivalentTo(correctArray);
41+
}
42+
43+
[Test]
44+
public static void ArrayShuffled_NewArraySameShuffle(
45+
[Random(0, 1000, 2, Distinct = true)] int n,
46+
[Random(1000, 10000, 5, Distinct = true)] int seed)
47+
{
48+
// Arrange
49+
var shuffler = new RecursiveShuffler<int>();
50+
var (correctArray, testArray) = RandomHelper.GetArrays(n);
51+
52+
// Act
53+
shuffler.Shuffle(testArray, seed);
54+
shuffler.Shuffle(correctArray, seed);
55+
56+
// Assert
57+
correctArray.Should().BeEquivalentTo(testArray, options => options.WithStrictOrdering());
58+
}
59+
}
60+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
3+
namespace Algorithms.Shufflers
4+
{
5+
/// <summary>
6+
/// Recursive Shuffler is a recursive version of
7+
/// Fisher-Yates shuffle algorithm. This can only be used
8+
/// for educational purposes due to stack depth limits.
9+
/// </summary>
10+
/// <typeparam name="T">Type array input.</typeparam>
11+
public class RecursiveShuffler<T> : IShuffler<T>
12+
{
13+
/// <summary>
14+
/// This is the public overload method that calls the private overload method.
15+
/// </summary>
16+
/// <param name="array">Array to shuffle.</param>
17+
/// <param name="seed">Random generator seed. Used to repeat the shuffle.</param>
18+
public void Shuffle(T[] array, int? seed = null)
19+
{
20+
Shuffle(array, array.Length - 1, seed);
21+
}
22+
23+
/// <summary>
24+
/// First, it will check the length of the array on the base case.
25+
/// Next, if there's still items left, it will shuffle the sub-array.
26+
/// Lastly, it will randomly select index from 0 to number of items of the array
27+
/// then swap the elements array[items] and array[index].
28+
/// </summary>
29+
/// <param name="array">Array to shuffle.</param>
30+
/// <param name="items">Number of items in the array.</param>
31+
/// <param name="seed">Random generator seed. Used to repeat the shuffle.</param>
32+
private void Shuffle(T[] array, int items, int? seed)
33+
{
34+
if (items <= 0)
35+
{
36+
return;
37+
}
38+
39+
Shuffle(array, items - 1, seed);
40+
var random = seed is null ? new Random() : new Random(seed.Value);
41+
int index = random.Next(items + 1);
42+
(array[items], array[index]) = (array[index], array[items]);
43+
(array[items], array[index]) = (array[index], array[items]);
44+
}
45+
}
46+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ find more than one implementation for the same objective but using different alg
150150
* [Fisher-Yates Shuffler](./Algorithms/Shufflers/FisherYatesShuffler.cs)
151151
* [LINQ Shuffler](./Algorithms/Shufflers/LinqShuffler.cs)
152152
* [Naive Shuffler](./Algorithms/Shufflers/NaiveShuffler.cs)
153+
* [Recursive Shuffler](./Algorithms/Shufflers/RecursiveShuffler.cs)
153154
* [Sequences](./Algorithms/Sequences)
154155
* [A000002 Kolakoski](./Algorithms/Sequences/KolakoskiSequence.cs)
155156
* [A000004 Zero](./Algorithms/Sequences/ZeroSequence.cs)

0 commit comments

Comments
 (0)