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.
		
		
		
		
		
			
		
			
				
					95 lines
				
				1.9 KiB
			
		
		
			
		
	
	
					95 lines
				
				1.9 KiB
			| 
											3 years ago
										 | /** | ||
|  |  * Obliterator Permutations Function | ||
|  |  * ================================== | ||
|  |  * | ||
|  |  * Iterator returning permutations 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]]; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Permutations. | ||
|  |  * | ||
|  |  * @param  {array}    array - Target array. | ||
|  |  * @param  {number}   r     - Size of the subsequences. | ||
|  |  * @return {Iterator} | ||
|  |  */ | ||
|  | module.exports = function permutations(array, r) { | ||
|  |   if (!Array.isArray(array)) | ||
|  |     throw new Error( | ||
|  |       'obliterator/permutations: first argument should be an array.' | ||
|  |     ); | ||
|  | 
 | ||
|  |   var n = array.length; | ||
|  | 
 | ||
|  |   if (arguments.length < 2) r = n; | ||
|  | 
 | ||
|  |   if (typeof r !== 'number') | ||
|  |     throw new Error( | ||
|  |       'obliterator/permutations: second argument should be omitted or a number.' | ||
|  |     ); | ||
|  | 
 | ||
|  |   if (r > n) | ||
|  |     throw new Error( | ||
|  |       'obliterator/permutations: the size of the subsequences should not exceed the length of the array.' | ||
|  |     ); | ||
|  | 
 | ||
|  |   var indices = new Uint32Array(n), | ||
|  |     subsequence = new Array(r), | ||
|  |     cycles = new Uint32Array(r), | ||
|  |     first = true, | ||
|  |     i; | ||
|  | 
 | ||
|  |   for (i = 0; i < n; i++) { | ||
|  |     indices[i] = i; | ||
|  | 
 | ||
|  |     if (i < r) cycles[i] = n - i; | ||
|  |   } | ||
|  | 
 | ||
|  |   i = r; | ||
|  | 
 | ||
|  |   return new Iterator(function next() { | ||
|  |     if (first) { | ||
|  |       first = false; | ||
|  |       indicesToItems(subsequence, array, indices, r); | ||
|  |       return {value: subsequence, done: false}; | ||
|  |     } | ||
|  | 
 | ||
|  |     var tmp, j; | ||
|  | 
 | ||
|  |     i--; | ||
|  | 
 | ||
|  |     if (i < 0) return {done: true}; | ||
|  | 
 | ||
|  |     cycles[i]--; | ||
|  | 
 | ||
|  |     if (cycles[i] === 0) { | ||
|  |       tmp = indices[i]; | ||
|  | 
 | ||
|  |       for (j = i; j < n - 1; j++) indices[j] = indices[j + 1]; | ||
|  | 
 | ||
|  |       indices[n - 1] = tmp; | ||
|  | 
 | ||
|  |       cycles[i] = n - i; | ||
|  |       return next(); | ||
|  |     } else { | ||
|  |       j = cycles[i]; | ||
|  |       tmp = indices[i]; | ||
|  | 
 | ||
|  |       indices[i] = indices[n - j]; | ||
|  |       indices[n - j] = tmp; | ||
|  | 
 | ||
|  |       i = r; | ||
|  | 
 | ||
|  |       indicesToItems(subsequence, array, indices, r); | ||
|  |       return {value: subsequence, done: false}; | ||
|  |     } | ||
|  |   }); | ||
|  | }; |