using System; using System.Collections.Generic; using System.Security.Cryptography; namespace DominionBase.Utilities { public static class Shuffler { /// /// Performs an in-place shuffle of the list provided using strong crypto to guarantee a randomized shuffling /// /// Type of object to be shuffled (unimportant for this method) /// List of items to be shuffled public static void Shuffle(IList list) { RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); int n = list.Count; while (n > 1) { byte[] box = new byte[1]; do provider.GetBytes(box); while (!(box[0] < n * (Byte.MaxValue / n))); int k = (box[0] % n); n--; T value = list[k]; list[k] = list[n]; list[n] = value; } } public static T Choose(IList list) { RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); byte[] box = new byte[1]; do provider.GetBytes(box); while (!(box[0] < list.Count * (Byte.MaxValue / list.Count))); int k = (box[0] % list.Count); return list[k]; } } public static class Gaussian { private static Boolean _HaveNextNextGaussian = false; private static Double _NextNextGaussian = 0d; private static Random _Random = null; /// /// Returns a random number with a Gaussian distribution with a mean of 0 and a standard deviation of 1 /// /// A random number with a Gaussian distribution with a mean of 0 and a standard deviation of 1 public static Double NextGaussian() { if (_HaveNextNextGaussian) { _HaveNextNextGaussian = false; return _NextNextGaussian; } else { if (_Random == null) _Random = new Random(); double v1, v2, s; do { v1 = 2.0 * _Random.NextDouble() - 1; // between -1.0 and 1.0 v2 = 2.0 * _Random.NextDouble() - 1; // between -1.0 and 1.0 s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = Math.Sqrt(-2 * Math.Log(s) / s); _NextNextGaussian = v2 * multiplier; _HaveNextNextGaussian = true; return v1 * multiplier; } } } }