// straighforward choose(n,r) combinations
function choose(ns,r){
if (r > ns.length) return [];
var res = [];
function _choose(i,_res){
if (_res.length == r){
res.push(_res);
return;
} else if (_res.length + ns.length - i == r){
_res = _res.concat(ns.slice(i));
res.push(_res);
return
}
var temp = _res.slice();
temp.push(ns[i]);
_choose(i + 1,temp);
_choose(i + 1,_res);
}
_choose(0,[]);
return res;
}
// function to collect an array without specified indexes
function remove(arr,indexSet){
var _arr = [];
arr.forEach(function(v,i){ if (!indexSet.has(i)) _arr.push(arr[i]); });
return _arr;
}
// main function
// the multiset is formatted as {element: [multiplicity,indexes]}
function removeAllCombs(arr,multiset){
var res = [];
// record the positions of multiset elements in the array
arr.forEach(function(v,i){
if (multiset[v]) multiset[v][1].push(i);
});
var keys = Object.keys(multiset);
function enumerate(i,accum){
if (i == keys.length){
res.push(remove(arr,new Set(accum)));
return;
}
var combs = choose(multiset[keys[i]][1],multiset[keys[i]][0]);
for (let j in combs){
var _accum = accum.slice();
_accum = _accum.concat(combs[j]);
enumerate(i + 1,_accum);
}
}
enumerate(0,[]);
return res;
}
console.log(JSON.stringify(
removeAllCombs([1,2,1,3,1,4,4],{1: [1,[]], 4: [2,[]]})
));