public void TestRandomness(Func<List<int>> getRandomList, int rangeLength, int count)
{
long combinations = (long)(rangeLength.Factorial(rangeLength - count + 1) * ((double)(count - 1) / count));
long iterations = combinations * 100;
var partitioner = Partitioner.Create(0, iterations, iterations / 4);
ConcurrentDictionary<long, int> ocurrences = new ConcurrentDictionary<long, int>(Environment.ProcessorCount, (int)combinations);
Parallel.ForEach(partitioner, new ParallelOptions() {MaxDegreeOfParallelism = Environment.ProcessorCount},
range =>
{
//hopefully having a private dictionary will help concurrency
Dictionary<long, int> privateOcurrences = new Dictionary<long, int>();
for (long i = range.Item1; i < range.Item2; ++i)
{
var list = getRandomList();
long acc = 0;
//this will only work when numbers are between 0 and 88
foreach (var value in list)
{
acc = (value + 11) + acc*100;
}
privateOcurrences.AddOrUpdate(acc, 1, v => v + 1);
}
foreach (var privateOcurrence in privateOcurrences)
{
ocurrences.AddOrUpdate(privateOcurrence.Key,
privateOcurrence.Value,
(k, v) => v + privateOcurrence.Value);
}
});
double averageOcurrences = iterations / combinations;
double currentAverage = ocurrences.Values.Average();
Debug.WriteLine("The average ocurrences of this implementation is {0} comparing to {1} in the 'perfect' scenario", currentAverage, averageOcurrences);
Assert.Less(currentAverage, averageOcurrences * 1.05);
Assert.Greater(currentAverage, averageOcurrences * 0.95);
}
[Test]
public void TestShuffleRandomness()
{
TestRandomness(() => Enumerable.Range(0, 1516).ToList().Shuffle().Take(4).ToList(), 16, 4);
}
public static IEnumerable<int> BobFloydNonRepeatingSequence(int min, int max, int count, int? seed = null)
{
Random random;
if (seed != null)
{
random = new Random(seed.Value);
}
else
{
random = new Random();
}
long length = max - min + 1;
INonRepeatingList values = NonRepeatingListFactory.GetNonRepeatingList(min, max, count);
for (int i = (int)(length - count); i < length; ++i)
{
if (!values.Add(random.Next(min, i+mini+min+1)))
{
values.Add(i+min);
}
}
return values;
}
[Test]
public void TestLastCountElementsAreNotInIndex0()
{
for (int i = 0; i < 1000000; ++i)
{
var list = Sequence.BobFloydNonRepeatingSequence(0, 15, 4).ToList();
Assert.IsFalse(new[] { 12, 13, 14, 15 }.Contains(list[0]));
Assert.AreEqual(4, list.Count);
}
}
[Test]
public void TestBobFloydBecomesLinear()
{
var list = Sequence.BobFloydNonRepeatingSequence(0, 15, 16).ToList();
for (int i = 0; i < list.Count; ++i)
{
Assert.AreEqual(i, list[i]);
}
}
public static IEnumerable<int> NonRepeatingRandomSequence(int min, int max, int count, int? seed = null)
{
Random random;
if (seed != null)
{
random = new Random(seed.Value);
}
else
{
random = new Random();
}
long length = max - min + 1;
INonRepeatingList values = NonRepeatingListFactory.GetNonRepeatingList(min, max, count);
for (int i = (int)(length - count); i < length; ++i)
{
if (!values.Add(random.Next(min, i+mini+min+1)))
{
values.Add(i+min);
}
}
values.Shuffle();
return values;
}