Advertisement
stefanpu

genereate all k- combinations for numbers [1,2,...n]

Jan 12th, 2013
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.47 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace _21.GenerateCombinations
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {          
  10.  
  11.             Console.Write("Enter n: ");
  12.             int n = int.Parse(Console.ReadLine());
  13.  
  14.             Console.Write("Enter k: ");
  15.             int k = int.Parse(Console.ReadLine());
  16.  
  17.          
  18.  
  19.             if (n <= 0)
  20.             {
  21.                 Console.WriteLine("n must be bigger than 0");
  22.                 return;
  23.             }
  24.  
  25.             if (n<0 || k< 0)
  26.             {
  27.                 Console.WriteLine("Both n and k must be greater than 0,");
  28.                 return;                
  29.             }
  30.  
  31.             if (n < k)
  32.             {
  33.                 Console.WriteLine("n must be bigger than k");
  34.                 return;
  35.             }
  36.  
  37.             //Note: new List<int>(n) means list with CAPACITY of n; its actual count is still 0.
  38.             //So you can`t have method of the type "InitializeList(list);" but you can have
  39.             // method of the type "InitializeArray( combination);"
  40.             List<int> list = new List<int>(n) ;
  41.             InitializeList(list, n);
  42.            
  43.             int[] combination = new int[k];
  44.            
  45.             InitializeArray( combination);
  46.  
  47.             bool nextCombinationExists = true;
  48.  
  49.             //Returns all combinations without repetitions
  50.             do
  51.             {
  52.                 PrintCombination(combination);
  53.  
  54.                 nextCombinationExists = NextIndexCombination(list.Count, k, combination);
  55.  
  56.             } while (nextCombinationExists);
  57.         }
  58.  
  59.         private static void InitializeList(List<int> list, int count)
  60.         {
  61.             for (int i = 1; i <=count ; i++)
  62.             {
  63.                 list.Add(i);                
  64.             }
  65.         }
  66.  
  67.         private static void PrintCombination(int[] comb)
  68.         {
  69.             for (int i = 0; i < comb.Length; i++)
  70.             {
  71.                 Console.Write((comb[i] + 1) +" ");
  72.                
  73.             }
  74.             Console.WriteLine();
  75.         }
  76.        
  77.         //Explanation of the method.
  78.         #region
  79.         /*The method generates next k-combination of indexes without repetition,
  80.           for given n, k and current combination of indexes.
  81.          
  82.          *The logic behind the method:
  83.           1. The idea of int[] arrayOfIndexes is to represent indexes in another array. After changing
  84.           values in arrayOfIndexes, we can access the values in the other array:
  85.          
  86.           arrayOfIndexes = {0, 1, 2} ; otherArray = {'a', 'b', 'c', 'd', 'e'} result: a, b, c
  87.           arrayOfIndexes = {0, 1, 3} ; otherArray = {'a', 'b', 'c', 'd', 'e'} result: a, b, d
  88.           arrayOfIndexes = {0, 1, 4} ; otherArray = {'a', 'b', 'c', 'd', 'e'} result: a, b, e
  89.           arrayOfIndexes = {0, 2, 3} ; otherArray = {'a', 'b', 'c', 'd', 'e'} result: a, c, d
  90.           ..................................................................................        
  91.          
  92.           NOTE: in case of otherArray of type {1, 2, 3, .... n} arrayOfIndexes[i] + 1 == otherArray[i]                  
  93.          
  94.           2. int[] arrayOfIndexes is a reference type - that means that the method modifies it.          
  95.           See: http://pastebin.com/R6kbsqJw          
  96.          
  97.           3. See http://en.wikipedia.org/wiki/File:Combinations_without_repetition;_5_choose_3.svg
  98.          We have combinations of 5 items taken 3 at a time, without repetition
  99.          
  100.           What happens in the picture:
  101.                 1. The last item increases by one until it reaches its max value - the max
  102.                 value of the last item is 5.
  103.                 2. Then, the next item makes the same thing, only its max value is 5 - 1.
  104.                 3. The the next - with max value 5 - 2. And so on...
  105.                 ....................
  106.                 ....................
  107.                 So, there is a max value that each item has to reach before the next item is changed.
  108.                 Max value formula: maxIndex - (kClass - 1 - currentIndex), where
  109.                     - maxIndex = n - 1, where n - the count of all items
  110.                     - kClass = k,  the class of the combination
  111.                     - currentIndex - the index of the current item in arrayOfIndexes.  
  112.          
  113.          How the algoritm works:
  114.          
  115.          foreach item in arrayOfIndexes(but starting from the last and going to the first) we check
  116.          if this item has not reached its max value
  117.                - if it hasn`t:
  118.                        1. get index of that item (itemIndex = currentIndex;)
  119.                        2. arrayOfIndexes[itemIndex]++;
  120.                        3. every nextItem = previous item + 1  
  121.                        4. return true (combinationExists)
  122.                - if it has:
  123.                        1. check next item while find such that hasn`t or iterate through all items.
  124.          
  125.          If all items have reached its max value. "itemIndex" remains equal to "kClass".
  126.          In that case no more combinations exist.            
  127.          */
  128.         #endregion
  129.         static bool NextIndexCombination(int elementsCount, int kClass, int[] arrayOfIndexes)
  130.         {
  131.             int maxIndex = elementsCount - 1;
  132.             // Find the first item that has not reached its maximum value.
  133.             int itemIndex = kClass;
  134.             for (int currentIndex = arrayOfIndexes.Length - 1; currentIndex >= 0; currentIndex--)
  135.             {
  136.                 if (arrayOfIndexes[currentIndex] < maxIndex - (kClass - 1 - currentIndex))
  137.                 {
  138.                     itemIndex = currentIndex;
  139.                     break;
  140.                 }
  141.             }
  142.  
  143.             // No more combinations to be generated. Every index has reached its
  144.             // maximum value.
  145.             if (itemIndex == kClass)
  146.             {
  147.                 return false;
  148.             }
  149.             // Genereate the next combination in lexographical order.
  150.             arrayOfIndexes[itemIndex]++;
  151.             for (int i = itemIndex + 1; i < arrayOfIndexes.Length; i++)
  152.             {
  153.                 arrayOfIndexes[i] = arrayOfIndexes[i - 1] + 1;
  154.             }
  155.  
  156.             return true;
  157.         }
  158.  
  159.         static void InitializeArray(int[] combination)
  160.         {
  161.             for (int i = 0; i < combination.Length; i++)
  162.             {
  163.                 combination[i] = i;                
  164.             }
  165.         }
  166.     }
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement