1

I am not a programmer, but I got a task that could be done manually or algorithmically. Doing it manually is time-consuming and error-prone. I, unfortunately, don't know where to begin.

Given the array [1, 2, 3, 4]

How to reduce it the following way:

[2, 3, 4] 1 out

[1, 3, 4] 2 out

[1, 2, 4] 3 out

[1, 2, 3] 4 out

[3, 4] 1, 2 out

[2, 4] 1, 3 out

[2, 3] 1, 4 out

[1, 4] 2, 3 out

[1, 3] 2, 4 out

[1, 2] 3, 4 out

[4] 1, 2, 3 out

[3] 1, 2, 4 out

[2] 1, 3, 4 out

[1] 2, 3, 4 out

The larger the array, the more variations. The sequence is not random, but there is a pattern that I cannot describe in words.

Thank you

fubar
  • 16,918
  • 4
  • 37
  • 43
Yunielf
  • 97
  • 1
  • 6
  • I see the pattern, but what exactly does your desired output look like? Lines of text, including the `1 out` etc? An array of arrays? – David784 Jul 01 '20 at 21:33
  • @David784 Yes, pretty much that way. – Yunielf Jul 01 '20 at 21:35
  • What you describe looks like a power set with the null set and the set that equals the original set omitted. I could take a crack and coding this up. Does it need to be in JavaScript? – freqnseverity Jul 01 '20 at 21:36
  • @freqnseverity thank you. At least I know a little bit how to run JS code in replit. – Yunielf Jul 01 '20 at 21:39
  • What you are trying to do is called a combination of `k` elements from a set (array) of `n` elements. See [Wikipedia](https://en.wikipedia.org/wiki/Combination). In your case you are varying k from `1` to `n-1` elements. – R. Schifini Jul 01 '20 at 21:48
  • You could adapt [this answer](https://stackoverflow.com/questions/43241174/javascript-generating-all-combinations-of-elements-in-a-single-array-in-pairs) that only combines 2 elements. – R. Schifini Jul 01 '20 at 21:50
  • Does this answer your question? [Javascript - Generating all combinations of elements in a single array (in pairs)](https://stackoverflow.com/questions/43241174/javascript-generating-all-combinations-of-elements-in-a-single-array-in-pairs) – R. Schifini Jul 01 '20 at 21:56
  • [This answer](https://stackoverflow.com/a/47204248/1730017) should work by varying `n`. – R. Schifini Jul 01 '20 at 21:57
  • @R.Schifini thank you, the solutions seems to be close to what I am looking for. – Yunielf Jul 01 '20 at 22:02

4 Answers4

2

Here is one way to do it:

function picks(arr) {
    // Indexes of the values that should be "out". -1 means nothing goes out.
    let out = Array(arr.length).fill(-1);
    let result = [];
    while (out[1] <= 0) {
        let i = arr.length;
        while (i-- && ++out[i] > i) {}
        for (let j = i+1; j < arr.length; j++) out[j] = out[j-1] + 1;
        let category = [[], []];
        for (let i = 0, j = 0; i < arr.length; i++) {
            while (out[j] < i) j++;
            category[+(out[j] === i)].push(arr[i]);
        }
        result.push(category);
    }
    return result;
}

// Demo run
let arr = [1, 2, 3, 4];
for (let [a, b] of picks(arr)) console.log(JSON.stringify(a), JSON.stringify(b)); 
trincot
  • 317,000
  • 35
  • 244
  • 286
2

To make this is of so much help use binary number. You are using a array with a size of 4, so you need first to do 2 raise to 4, which is 16. Now you make a loop that will be storing in a array each number from 1 to 16 in binary.

var arr[16];
  for (i = 0; i < 16; i++) {
  arr[i]=binary(i);
}

The function to calculate the binary could be the following:

string binario(int n){
    if(n>=2) {
        binario(n/2); 
        arr[n].concat(""+n%2);
    }
    else {
        arr[n].concat(""+n);
    }
}

When you have this, is time to print every case using the previous array var arr_original[16];

for (let i = 0; i < 16; i++) {
    for (let j = 0; j < 4; j++) {
        if (j+1==1) {
            if (arr[i][j]) {
                arr_original[i][j] = "1";
            }else{
                arr_original[i][j] = "0";
            }
        }
        if (j+1 == 2) {
            if (arr[i][j]) {
                arr_original[i][j] = "1";
            } else {
                arr_original[i][j] = "0";
            }
        }
        if (j+1 == 3) {
            if (arr[i][j]) {
                arr_original[i][j] = "1";
            } else {
                arr_original[i][j] = "0";
            }
        }
        if (j+1 == 4) {
            if (arr[i][j]) {
                arr_original[i][j] = "1";
            } else {
                arr_original[i][j] = "0";
            }
        }
    }
}

This code will give you every permutation of your array. I don't know too much about javascript and I think there are some syntax errors, but the algorithm is functional. I hope you could make it!

Juventino
  • 51
  • 1
  • 1
  • 6
1

Recursive solution for this

const result = [];

function combinations(arr, size){
    for(let i=(arr[arr.length > 0 ? arr.length-1:0 ] || 0) + 1; i<=size; i++)
    {
        let comb = arr.concat(i);
        result.push(comb);
        combinations(comb, size);
    }
}
combinations([],5);

console.log(JSON.stringify(result));

Number of terms will be

(if we include the original array)

nC1 + nC2 + nC3 ...... + nCn = 2n-1

namar sood
  • 1,580
  • 1
  • 9
  • 17
1

Expanding on @Juventino, with binaris:

function binary(dec, bits) {
  var b=[];
  var d=dec;
  while(d>0) {
    var r=d%2;
    b.unshift(r);
    d=Math.floor(d/2);
  }
  while(b.length<bits) b.unshift(0);
  return b;
}
array=[1,2,3,4]
for(var i=15; i>=0; i--) {
  var bi=binary(i, 4);
  var bxi=binary(15-i,4);
  //console.log(bi, bxi);
  var inArr=[];
  for(var ia=0; ia<bi.length; ia++) {
    if(bi[ia]==1) inArr.push(array[ia]);
  }
  var outArr=[];
  for(var oa=0; oa<bxi.length; oa++) {
    if(bxi[oa]==1) outArr.push(array[oa]);
  }
  console.log(inArr, outArr);
}

Output:

> (4) [1, 2, 3, 4] []
> (3) [1, 2, 3] [4]
> (3) [1, 2, 4] [3]
> (2) [1, 2] (2) [3, 4]
> (3) [1, 3, 4] [2]
> (2) [1, 3] (2) [2, 4]
> (2) [1, 4] (2) [2, 3]
> [1] (3) [2, 3, 4]
> (3) [2, 3, 4] [1]
> (2) [2, 3] (2) [1, 4]
> (2) [2, 4] (2) [1, 3]
> [2] (3) [1, 3, 4]
> (2) [3, 4] (2) [1, 2]
> [3] (3) [1, 2, 4]
> [4] (3) [1, 2, 3]
> [] (4) [1, 2, 3, 4]
iAmOren
  • 2,760
  • 2
  • 11
  • 23