Пример #1
0
        private void CalcRank()
        {
            int isUsed = 0;
            int toGo   = Choices;

            rank = 0;

            foreach (int e1 in this.data)
            {
                isUsed |= 1 << e1;

                int digit = 0;
                for (int e2 = 0; e2 < e1; ++e2)
                {
                    if ((isUsed & 1 << e2) == 0)
                    {
                        ++digit;
                    }
                }

                rank += digit * Combinatoric.Factorial(--toGo);
            }

            if (toGo != 0)
            {
                rank /= Combinatoric.Factorial(toGo);
            }
        }
        /// <summary>
        /// Initializes a new multicombination from elements supplied in <em>source</em> picked
        /// from the supplied number of <em>choices</em>.
        /// </summary>
        /// <param name="choices">Number of values to pick from.</param>
        /// <param name="source">Array of integers.</param>
        /// <remarks>
        /// Supplying a value for <em>choices</em> that is greater than the number of elements in <em>source</em>
        /// will instantiate a <em>k</em>-multicombination also known as a <em>k</em>-combination with repetition.
        /// </remarks>
        /// <example><code source="..\Examples\Multicombination\McExample04\McExample04.cs" lang="cs"/></example>
        /// <exception cref="ArgumentNullException">When <em>source</em> is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">When <em>source</em> contains invalid data; when <em>choices</em> is 0 and <em>source</em> is not empty.</exception>
        public Multicombination(int choices, int[] source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (choices < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is less than zero.");
            }
            if (choices == 0 && source.Length > 0)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is zero and picks is nonzero.");
            }

            this.data = new int[source.Length];
            source.CopyTo(this.data, 0);
            Array.Sort(this.data);

            this.choices = choices;
            CalcRowCount();

            foreach (int element in this.data)
            {
                if (element < 0 || element >= choices)
                {
                    throw new ArgumentOutOfRangeException(nameof(source), "Element is out of range.");
                }
            }

            //
            // Perform ranking:
            //

            this.rank = 0;
            if (RowCount == 0)
            {
                return;
            }

            int comboElement = this[0];
            int ji           = 0;

            for (int ki = 0;;)
            {
                for (; ji < comboElement; ++ji)
                {
                    this.rank += Combinatoric.BinomialCoefficient(Choices + Picks - ji - 2, Picks - ki - 1);
                }

                ++ki;
                if (ki >= Picks)
                {
                    break;
                }

                ji           = comboElement + 1;
                comboElement = this[ki] - this[ki - 1] + ji;
            }
        }
Пример #3
0
        /// <summary>
        /// Initializes a new combination from elements supplied in <em>source</em> picked
        /// from the supplied number of <em>choices</em>.
        /// </summary>
        /// <param name="choices">Number of values to pick from.</param>
        /// <param name="source">Array of integers.</param>
        /// <remarks>
        /// Supplying a value for <em>choices</em> that is greater than the number of elements in <em>source</em>
        /// will instantiate a <em>k</em>-combination also known as a pick-combination.
        /// </remarks>
        /// <example><code source="..\Examples\Combination\CnExample04\CnExample04.cs" lang="cs"/></example>
        /// <exception cref="ArgumentNullException">When <em>source</em> is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// When length of <em>source</em> is greater than <em>picks</em>; when <em>source</em> contains invalid data.
        /// </exception>
        public Combination(int choices, int[] source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (choices < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is less than zero.");
            }
            if (choices < source.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is less than picks.");
            }

            this.data = new int[source.Length];
            source.CopyTo(this.data, 0);
            Array.Sort(this.data);

            this.choices = choices;
            CalcRowCount();

            for (int ki = 0; ki < Picks; ++ki)
            {
                if (this[ki] < 0 || this[ki] >= choices)
                {
                    throw new ArgumentOutOfRangeException(nameof(source), "Element is out of range.");
                }
                else if (ki > 0 && this[ki] == this[ki - 1])
                {
                    throw new ArgumentOutOfRangeException(nameof(source), "Elements must be unique.");
                }
            }

            //
            // Perform ranking:
            //

            this.rank = 0;
            int ji = 0;

            for (int ki = 0; ki < Picks; ++ki)
            {
                for (; ji < this[ki]; ++ji)
                {
                    this.rank += Combinatoric.BinomialCoefficient(Choices - ji - 1, Picks - ki - 1);
                }

                ji = this[ki] + 1;
            }
        }
Пример #4
0
 private void CalcRowCount()
 {
     if (Picks == 0)
     {
         rowCount = 0;
     }
     else
     {
         rowCount = Combinatoric.Factorial(Choices);
         if (Choices != Picks)
         {
             rowCount /= Combinatoric.Factorial(Choices - Picks);
         }
     }
 }
Пример #5
0
        // On entry: elements allocated for choices.
        // On exit: result will be in elements.
        private static void CalcPlainUnrank(int[] elements, long plainRank)
        {
            elements[0] = 0;
            for (int ei = 1; ei < elements.Length; ++ei)
            {
                int yd = (int)(Combinatoric.Factorial(elements.Length) / Combinatoric.Factorial(ei + 1));
                int yi = (int)((plainRank / yd) % ((ei + 1) * 2));
                int ip = yi <= ei ? ei - yi : yi - ei - 1;

                for (int si = ei; si > ip; --si)
                {
                    elements[si] = elements[si - 1];
                }
                elements[ip] = ei;
            }
        }
Пример #6
0
        /// <summary>Initializes a new permutation of <see cref="Rank"/> 0 with the supplied number of elements.</summary>
        /// <param name="choices">Number of elements in the sequence.</param>
        /// <example><code source="..\Examples\Permutation\PnExample01\PnExample01.cs" lang="cs"/></example>
        /// <exception cref="ArgumentOutOfRangeException">When <em>choices</em> is less than 0 or greater than 20.</exception>
        public Permutation(int choices)
        {
            if (choices < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is less than zero.");
            }
            if (choices > MaxChoices)
            {
                throw new ArgumentOutOfRangeException(nameof(choices), "Value is greater than maximum allowed.");
            }

            this.data = new int[choices];
            for (int ei = 0; ei < choices; ++ei)
            {
                this[ei] = ei;
            }

            this.choices  = choices;
            this.rowCount = choices == 0 ? 0 : Combinatoric.Factorial(choices);
            this.rank     = 0;
        }
Пример #7
0
 private void CalcRowCount()
 => rowCount = Picks == 0 ? 0 : Combinatoric.BinomialCoefficient(Choices, Picks);