1

I want to construct a function showNum(ar,k) getting all the k-digit numbers from array ar.

For example, showNum([1,2,3],2) should return 12,13,21,23,31,32

andshowNum([1,2,3],1) should return 1,2,3.

My code works well with the case that k is fix.

For instance, the case k is 3.

My idea is to loop 3 times.

   function showNum(a){
   var ar = [];
   var n = a.length;
   for(i = 0; i <= n; i++){
       for(j = 0; j <= n; j++){
           for(k = 0; k <= n; k++){
           if(a[i] != a[j] && a[i] != a[k] && a[k] != a[j]) ar.push(a[i]*100 + a[j]*10 + a[k]);
           }
       }
   }
   return ar;
}

But when k is arbitrarily less than n, I don't know how to loop.

Godgog Arsenal
  • 107
  • 1
  • 8
  • 2
    In this case, you'll want to try to research generating binary range algorithm https://stackoverflow.com/questions/1851134/generate-all-binary-strings-of-length-n-with-k-bits-set – Kien Pham Apr 25 '19 at 10:37

1 Answers1

3

Recursion is really helpful here: Inside of the loop, make a recursive call to iterate the numbers again. This can be done easily using a generator:

 function* combinations(values, depth, previous = []) {
   if(depth <=0) {
     yield previous.reduce((res, n, i) => res + n * 10 ** i, 0);
     return;
  }

  for(const value of values) {
    if(previous.includes(value))
        continue;
    yield* combinations(values, depth - 1, [...previous, value]);
  }
}

Usable as:

 [...combinations([1, 2, 3], 2)]

function* combinations(values, depth, previous = []) {
  if(depth <=0) {
     yield previous.reduce((res, n, i) => res + n * 10 ** i, 0);
     return;
  }

  for(const value of values) {
    if(previous.includes(value))
        continue;
    yield* combinations(values, depth - 1, [...previous, value]);
  }
}

console.log([...combinations([1, 2, 3], 2)])
Fraction
  • 11,668
  • 5
  • 28
  • 48
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151