Example #1
0
        /// <summary>
        /// Get a random subset of the specified size from the provided List.
        /// </summary>
        public static IList <T> RandomSubset <T>(this IList <T> list, int n, System.Random rng = null)
        {
            if (list.Count < n)
            {
                throw new ArgumentOutOfRangeException($"Can't select a random subset of {n} items from a list of {list.Count} items.");
            }

            if (rng == null)
            {
                rng = _rng;
            }
            IList <int> indices = rng.Distinct(n, 0, list.Count);

            List <T> output = new List <T>(n);

            foreach (int index in indices)
            {
                output.Add(list[index]);
            }

            return(output);
        }
Example #2
0
        /// <summary>
        /// Generate N random positive (optionally including 0) integers that sum to the specified
        /// total.
        /// </summary>
        public static IList <int> SumTo(
            this System.Random rng,
            int n,
            int sum,
            bool allowZero = false
            )
        {
            if (n <= 0 || sum <= 0)
            {
                throw new ArgumentException($"Can't generate {n} numbers that sum to {sum}.");
            }

            if (!allowZero && n > sum)
            {
                throw new ArgumentException($"Can't generate {n} non-zero numbers that sum to {sum}.");
            }

            // Generate a list of N-1 random numbers between 0 and sum, which will act as
            // partition points between the output random numbers.
            IList <int> divisions = allowZero
                ? rng.Many(n - 1, 0, sum, true)
                : rng.Distinct(n - 1, 1, sum, true);

            // Add each partition width to the list of output numbers.
            List <int> output       = new List <int>();
            int        lastDivision = 0;

            for (int i = 0; i < divisions.Count; ++i)
            {
                output.Add(divisions[i] - lastDivision);
                lastDivision = divisions[i];
            }
            output.Add(sum - lastDivision);

            return(output);
        }