You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
1.7 KiB
77 lines
1.7 KiB
/**
|
|
* Obliterator Combinations Function
|
|
* ==================================
|
|
*
|
|
* Iterator returning combinations of the given array.
|
|
*/
|
|
var Iterator = require('./iterator.js');
|
|
|
|
/**
|
|
* Helper mapping indices to items.
|
|
*/
|
|
function indicesToItems(target, items, indices, r) {
|
|
for (var i = 0; i < r; i++) target[i] = items[indices[i]];
|
|
}
|
|
|
|
/**
|
|
* Combinations.
|
|
*
|
|
* @param {array} array - Target array.
|
|
* @param {number} r - Size of the subsequences.
|
|
* @return {Iterator}
|
|
*/
|
|
module.exports = function combinations(array, r) {
|
|
if (!Array.isArray(array))
|
|
throw new Error(
|
|
'obliterator/combinations: first argument should be an array.'
|
|
);
|
|
|
|
var n = array.length;
|
|
|
|
if (typeof r !== 'number')
|
|
throw new Error(
|
|
'obliterator/combinations: second argument should be omitted or a number.'
|
|
);
|
|
|
|
if (r > n)
|
|
throw new Error(
|
|
'obliterator/combinations: the size of the subsequences should not exceed the length of the array.'
|
|
);
|
|
|
|
if (r === n) return Iterator.of(array.slice());
|
|
|
|
var indices = new Array(r),
|
|
subsequence = new Array(r),
|
|
first = true,
|
|
i;
|
|
|
|
for (i = 0; i < r; i++) indices[i] = i;
|
|
|
|
return new Iterator(function next() {
|
|
if (first) {
|
|
first = false;
|
|
|
|
indicesToItems(subsequence, array, indices, r);
|
|
return {value: subsequence, done: false};
|
|
}
|
|
|
|
if (indices[r - 1]++ < n - 1) {
|
|
indicesToItems(subsequence, array, indices, r);
|
|
return {value: subsequence, done: false};
|
|
}
|
|
|
|
i = r - 2;
|
|
|
|
while (i >= 0 && indices[i] >= n - (r - i)) --i;
|
|
|
|
if (i < 0) return {done: true};
|
|
|
|
indices[i]++;
|
|
|
|
while (++i < r) indices[i] = indices[i - 1] + 1;
|
|
|
|
indicesToItems(subsequence, array, indices, r);
|
|
return {value: subsequence, done: false};
|
|
});
|
|
};
|