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
			| 
											3 years ago
										 | /** | ||
|  |  * 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}; | ||
|  |   }); | ||
|  | }; |