[C#] 組合數學 (未完成)

  • 1585
  • 0

摘要:[C#] 組合數學 (未完成)

        /// 
        /// 提供進階的數學方法。
        /// 
        public class jsMath
        {
            /// 
            /// 計算n階乘的方法。
            /// 
            /// 
不為負數的整數
            public static uint Factorial(uint n, uint startN = 2)
            {
                // 0! = 1 (這是定義),所以最少也就是1。
                uint result = 1;

                // i = 2 是因為 1*1 還是等於1,所以省略從1開始。
                for (uint i = startN; i <= n; i++)
                    result *= i;

                return result;
            }
            /// 
            /// 計算n種取k種的排列數。
            /// 
            public static uint Permutation(uint n, uint k)
            {
                return Factorial(n, (n - k) +1);
                //return Factorial(n) / Factorial(n - k);     // 公式: http://zh.wikipedia.org/wiki/%E7%B5%84%E5%90%88%E6%95%B8%E5%AD%B8
            }
            /// 
            /// 計算n種取k種的組合數。
            /// 
            public static uint Combination(uint n, uint k)
            {
                return Permutation(n, k) / Factorial(k);    // 公式: http://zh.wikipedia.org/wiki/%E7%B5%84%E5%90%88%E6%95%B8%E5%AD%B8
            }
        }

        /// 
        /// 產生泛型的組合數學陣列結果。
        /// 
        /// 
        public class Combination
        {
            /// 
            /// 自定義形態清單表。
            /// 
            public T[] arrAll { get; private set; }
            /// 
            /// 要取得的數量。
            /// 
            public uint kSize { get; private set; }
            /// 
            /// 旋轉的總次數。
            /// 
            public uint totalRotateLength { get; private set; }
            /// 
            /// 目前旋轉的索引。
            /// 
            public uint curRotateIndex { get; private set; }
            /// 
            /// 是否已取得完畢?
            /// 
            public bool HasGetsEnd { get { return curRotateIndex >= this.totalRotateLength; } }

            /// 
            /// 初始化n清單與要取得的k大小。
            /// 
            public Combination(ref T[] arrT, uint kSize)
            {
                this.arrAll = arrT;
                this.kSize = kSize;
                uint n = (uint)arrAll.Length;
                uint k = kSize;
                if (n < k) throw new Exception();
                this.totalRotateLength = jsMath.Combination(n, k);
                this.curRotateIndex = 0;
            }

            /// 
            /// 取得下一個旋轉後的組合結果。
            /// 
            public T[] GetNextRotateResult()
            {
                // 取得目前次數的旋轉索引偏移陣列値。
                uint[] arrRotateIndexOffset = GetCurrentIndexOffset();
                T[] arrPartial = new T[arrRotateIndexOffset.Length];
                // 從旋轉的索引表數值對應到清單表中的數值複製k個出來。
                for (int i = 0; i < arrRotateIndexOffset.Length; i++)
                    arrPartial[i] = arrAll[arrRotateIndexOffset[i]];
                // 取得後,遞增為下一個索引値。
                this.curRotateIndex++;
                return arrPartial;
            }

            /// 
            /// 取得目前次數的旋轉索引偏移陣列値。
            /// 
            protected uint[] GetCurrentIndexOffset()
            {
                uint[] arrRotateIndexOffset = new uint[kSize];
                // 第一個索引固定不動,
                arrRotateIndexOffset[0] = (uint)(this.curRotateIndex % arrAll.Length);
                // 由第二個索引値開始往右移動,可以保持不重複的組合。
                for (uint i = 1; i < arrRotateIndexOffset.Length; i++)
                {
                    uint value = (uint)(arrRotateIndexOffset[0] + i + this.curRotateIndex / arrAll.Length);
                    arrRotateIndexOffset[i] = value < arrAll.Length ? value : value - (uint)arrAll.Length;
                }
                return arrRotateIndexOffset;
            }
        }