title: How to efficiently generate combination without repetition with certain distinctive number between them
body: <p><br/>How to efficiently generate sets of <b><i>number combination without repetition</i></b> where all sets has certain distinctive number between each other.
  <br/><b>*NOTE</b> : <i>Range number will always start from 0.</i></p>
  <hr />
  <h2><b>Example :</b></h2>
  <p>Range Number <b>(numbers[ ])</b> = 0,1,2,3,4,5,6,7  ==&gt; total 8 numbers <b>(n)</b>.
  <br/>Combination <b>(k)</b> = 5 numbers.
  <br/>Distinctive numbers <b>(nD)</b> = 2 numbers.</p>
  <p><br/><b>Results :</b>
  <br/>0 1 2 3 4
  <br/>0 1 2 5 6
  <br/>0 1 3 5 7
  <br/>0 1 4 6 7
  <br/>0 2 3 6 7
  <br/>0 2 4 5 7
  <br/>0 3 4 5 6
  <br/><b><i>There are 7 valid combinations</i></b></p>
  <hr />
  <h2><b>How it Assembled :</b></h2>
  <p>Since i'm not good with words, so let me visualized them as like this :
  <a href="https://i.stack.imgur.com/rFbRy.png" rel="noreferrer"><img src="https://i.stack.imgur.com/rFbRy.png" alt="enter image description here" /></a></p>
  <p>To explain about their distinctive numbers :
  <a href="https://i.stack.imgur.com/PaNiW.png" rel="noreferrer"><img src="https://i.stack.imgur.com/PaNiW.png" alt="enter image description here" /></a></p>
  <p>And we could summarize them into this table :
  <a href="https://i.stack.imgur.com/q8IaI.png" rel="noreferrer"><img src="https://i.stack.imgur.com/q8IaI.png" alt="enter image description here" /></a></p>
  <hr />
  <h2><b>What have i achieved so far</b></h2>
  <p>My current solution is very inefficient (or you can call it brute force).
  <br/>* First i loop for each combination. ==&gt;  <b>k C n</b>
  <br/>* Then i create a temp for valid combination.
  <br/>* Then for each combination i validate towards my temp, if its valid then  store it in temp, otherwise ignore it.
  <br/>Thats it.</p>
  <p>Here is my code in Console App :</p>
  <pre><code>class Program
  {
      static List&lt;int[]&gt; ValidCombinations;
  
      static void Main()
      {
          ValidCombinations = new List&lt;int[]&gt;();
  
          int[] numbers = Enumerable.Range(0, 8).ToArray();
          int n = numbers.Length;
          const int k = 5;
          const int nD = 2;
  
          int maxIntersect = k - nD;
  
          int iCombination = 0;
          int iValidCombination = 0;
          int[] _temp = new int[k];
          foreach (int[] c in FindCombinations(k, n))
          {
              // #Print out
              for (int i = 0; i &lt; n; i++)
              {
                  if (c.Contains(i))
                      Console.Write(c[Array.IndexOf(c, i)] + &quot; &quot;);
                  else
                      Console.Write(&quot;_ &quot;);
              }
  
              // Save to List
              if (IsValidSet(c, maxIntersect))
              {
                  _temp = new int[k];
                  for (int i = 0; i &lt; c.Length; i++)
                  {
                      _temp[i] = c[i];
                  }
                  ValidCombinations.Add(_temp);
                  iValidCombination++;
                  Console.Write(&quot; ### --&gt; {0}&quot;, string.Join(&quot; &quot;, c));
              }
              Console.WriteLine();
  
              iCombination++;
          }
          Console.WriteLine(&quot;\nTotal Combination = {0}&quot;, iCombination);
          Console.WriteLine(&quot;Valid Combination Found = {0}&quot;, iValidCombination);
      }
  
      public static IEnumerable&lt;int[]&gt; FindCombosRec(int[] buffer, int done, int begin, int end)
      {
          for (int i = begin; i &lt; end; i++)
          {
              buffer[done] = i;
  
              if (done == buffer.Length - 1)
                  yield return buffer;
              else
                  foreach (int[] child in FindCombosRec(buffer, done + 1, i + 1, end))
                      yield return child;
          }
      }
  
      public static IEnumerable&lt;int[]&gt; FindCombinations(int m, int n)
      {
          return FindCombosRec(new int[m], 0, 0, n);
      }
  
      private static bool IsValidSet(int[] set, int maxIntersect)
      {
          foreach (var item in ValidCombinations)
          {
              if (set.Intersect(item).Count() &gt; maxIntersect)
                  return false;
          }
  
          return true;
      }
  }
  </code></pre>
  <p>I got the base code to generate the combination from <a href="https://rosettacode.org/wiki/Combinations" rel="noreferrer">here</a>.</p>
  <hr />
  <h2><b>The Issues</b></h2>
  <p>This is work, but for greater range of numbers, this solution will takes a lot of time to complete. I know because the combination algorithm involved , but there must be some kind of shortcut or pattern to simplified it <i>(which my tiny brain has failed to figure it out)</i>.</p>
  <p><b>Thank you very much.</b></p>