Вот рекурсивная формулировка, которая будет перечислять комбинации реальных элементов.В списке [2,2]
каждый 2
считается отдельным элементом.Мы можем ввести произвольные шаблоны, такие как [1,2,3,4,5,6]
, разделенные на все комбинации с шаблоном [[x],[x,x],[x,x,x]]
.
function f(ns, subs){
if (ns.length != subs.reduce((a,b) => a+b))
throw new Error('Subset cardinality mismatch');
function g(i, _subs){
if (i == ns.length)
return [_subs];
let res = [];
const cardinalities = new Set();
function h(j){
let temp = _subs.map(x => x.slice());
temp[j].push(ns[i]);
res = res.concat(g(i + 1, temp));
}
for (let j=0; j<subs.length; j++){
if (!_subs[j].length && !cardinalities.has(subs[j])){
h(j);
cardinalities.add(subs[j]);
} else if (_subs[j].length && _subs[j].length < subs[j]){
h(j);
}
}
return res;
}
let _subs = [];
subs.map(_ => _subs.push([]));
return g(0, _subs);
}
console.log('\n[0,1,2,3], [2,2]:');
let str = '';
for (let i of f([0,1,2,3], [2,2]))
str += '\n' + JSON.stringify(i);
console.log(str);
console.log('\n[0,1,2,3], [1,3]:');
str = '';
for (let i of f([0,1,2,3], [1,3]))
str += '\n' + JSON.stringify(i);
console.log(str);
console.log('\n[0,1,2,3,4,5,6,7,8,9], [1,2,3,4]:');
str = '';
for (let i of f([0,1,2,3,4,5,6,7,8,9], [1,2,3,4]))
str += '\n' + JSON.stringify(i);
console.log(str);