0

I was trying to write a algorithm in javascript that returns all the possible 3 digit numbers numbers from a given array of length 6 For Example

var arr = [1, 2, 3, 4, 5, 6];

I have already got the combinations with the same sets of numbers in different positions in the 2D array. (The code which I took the help of)

If I have the same numbers in different combinations then I would like to remove them form the array. like I have [1, 2, 3] at index i in the array comtaining all the possible combinations then I would like to remove other combination with the same numbers like [2, 1, 3], [1, 3, 2] and so on..

Note the array also contains numbers repeated like [3, 3, 3], [2, 2, 2], [3, 2, 3] and so on

I expect an 2d array which has the values : [[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,3,4]] and so on (24 possibilities)

Is there any way to do this?

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Karan Gandhi
  • 303
  • 1
  • 2
  • 15

5 Answers5

3

Extending the answer you linked, just filter out the results with the help of a Set.

Sort an individual result, convert them into a String using join(), check if it's present in set or not, and if not, then store them in the final result.

function cartesian_product(xs, ys) {
  var result = [];
  for (var i = 0; i < xs.length; i++) {
    for (var j = 0; j < ys.length; j++) {
      // transform [ [1, 2], 3 ] => [ 1, 2, 3 ] and append it to result []
      result.push([].concat.apply([], [xs[i], ys[j]]));
    }
  }
  return result;
}

function cartesian_power(xs, n) {
  var result = xs;
  for (var i = 1; i < n; i++) {
    result = cartesian_product(result, xs)
  }
  return result;
}

function unique_cartesian_power(xs, n) {
  var result = cartesian_power(xs, n);
  var unique_result = [];
  const set = new Set();

  result.forEach(function(value) {
    var representation = value.sort().join(' ');
    if (!set.has(representation)) {
      set.add(representation);
      unique_result.push(value);
    }

  });

  return unique_result;
}


console.log(unique_cartesian_power([1, 2, 3, 4, 5, 6], 3));
nice_dev
  • 17,053
  • 2
  • 21
  • 35
1

const arr = [1, 2, 3, 4, 5, 6];

const result = arr.reduce((a, v) => arr.reduce((a, v2) => {
 arr.reduce((a, v3) => {
  const current = [v, v2, v3].sort().join(",");
  !a.find(_ => _.sort().join() === current) && a.push([v, v2, v3]);
  return a;
 }, a);
 return a;
}, a), []);

console.log(result.length);
console.log(...result.map(JSON.stringify));
ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
0

You could take an iterative and recursive approach by sorting the index and a temporary array for the collected values.

Because of the nature of going upwards with the index, no duplicate set is created.

function getCombination(array, length) {
    function iter(index, right) {
        if (right.length === length) return result.push(right);
        if (index === array.length) return;
        for (let i = index, l = array.length - length + right.length + 1; i < l; i++) {
            iter(i + 1, [...right, array[i]]);
        }
    }
    var result = [];
    iter(0, []);
    return result;
}

var array = [1, 2, 3, 4, 5, 6],
    result = getCombination(array, 3);

console.log(result.length);
result.forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Going index wise isn't the right idea. Case where this fails: `[2,1,3,2,4,5]` – nice_dev Nov 28 '19 at 13:41
  • Seems also to miss combinations: e.g. `[6,6,6]` – Christian Ulbrich Nov 28 '19 at 13:42
  • @vivek_23, what goes wrong? of duplicate values are not wanted, you could take an array with unique values as input. – Nina Scholz Nov 28 '19 at 13:47
  • @ChristianUlbrich, why `[6, 6, 6]`? – Nina Scholz Nov 28 '19 at 13:49
  • @NinaScholz Yours currently returns `[2,1,3]` and `[1,3,2]` as 2 different combinations which was supposed to be removed. We can't remove duplicates because sometimes they do provide a valid combination depending upon the input. Like for `[1,1,2,3,4]`, `[1,1,2]` is a valid combination. I was initially confused by OP's statement at first. – nice_dev Nov 28 '19 at 13:51
  • @NinaScholz `[6,6,6]` is a valid combination; at least this is how I understood OP. – Christian Ulbrich Nov 28 '19 at 13:56
0

This is a good example, that it is usually worthwhile not asking for a specific answer for a generic problem shown with a specific question; however as you've requested - if you really have the above constraints which kind of don't make much sense to me, you could do it like that:

function combine(firstDigits, secondDigits, thirdDigits) {

  let result = [];

  firstDigits.forEach(firstDigit => {
// combine with all secondDigitPermutations
secondDigits.forEach(secondDigit => {
  // combine with all thirdDigitPermutations
  thirdDigits.forEach(thirdDigit => {
    result.push([firstDigit, secondDigit, thirdDigit])
  })
})
  });

  // now we have all permutations and simply need to filter them
  // [1,2,3] is the same as [2,3,1]; so we need to sort them 
  // and check them for equality (by using a hash) and memoize them
  
  // [1,2,3] => '123'
  function hashCombination(combination) {
return combination.join('ಠ_ಠ');
  }

  return result
// sort individual combinations to make them equal
.map(combination => combination.sort())
.reduce((acc, currentCombination) => {
  // transform the currentCombination into a "hash"
  let hash = hashCombination(currentCombination); 
  // and look it up; if it is not there, add it to cache and result
  if (!(hash in acc.cache)) {
    acc.cache[hash] = true;
    acc.result.push(currentCombination);
  } 
  return acc;
  
}, {result: [], cache: {}})
.result;
}

console.log(combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).length);
console.log(...combine([1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]).map(JSON.stringify));

This does not include some super-clever assumptions about some index, but it does abuse the fact, that it's all about numbers. It is deliberately using no recursion, because this would easily explode, if the amount of combinations is going to be bigger and because recursion in itself is not very readable.

For a real world problem™ - you'd employ a somewhat similar strategy though; generating all combinations and then filter them. Doing both at the same time, is an exercise left for the astute reader. For finding combinations, that look different, but are considered to be the same you'd also use some kind of hashing and memoizing.

Christian Ulbrich
  • 3,212
  • 1
  • 23
  • 17
  • Use a delimiter when joining `combination.join('');`. This is because there could be overlapping joins. Like say we are looking for combinations of length 2. We can have combinations as `[12,3]` and the other as `[1,23]`. Without a delimiter, both would give `123`. – nice_dev Nov 29 '19 at 07:15
  • Good catch. Luckily it's just a simple change. :) – Christian Ulbrich Nov 29 '19 at 22:15
-1
let arr1 = [1,2,3,4,5,6];

function getCombination(arr){
    let arr2 = [];
    for(let i=0; i<arr.length; i++){
        for(let j=i; j<arr.length; j++){
            for(let k=j; k<arr.length; k++){
                arr2.push([arr[i],arr[j],arr[k]]);
            }   
        }
    }
    return arr2;
}

console.log(getCombination(arr1));
  • This does not satisfy OP's constraints concerning duplicates. – Christian Ulbrich Nov 28 '19 at 19:13
  • can you backup your claim with evidence (an example)? – Imrane Akkouh Nov 28 '19 at 20:40
  • you are **right** and I am **wrong**. I was too fast. Amazing, how simple this in the end can be; yours is probably the desired solution to this strange interview question. :) However I cannot upvote again; I am sorry. :( – Christian Ulbrich Nov 29 '19 at 22:14
  • i was only wandering if you noticed some mistake in my code that i didn't..i have no problem with the vote ,but i request you not to rush things in the futur..**continue the good work** – Imrane Akkouh Nov 30 '19 at 19:52
  • [1,1,13,1,1,1,2,1,1,1,1,1,1,1,1,1,1,17] results with a [2,2,17] subset for(let j=i+1; j – CJunk Jul 16 '22 at 19:31