Skip to content
Snippets Groups Projects
Commit 024c82ff authored by Alexander Rose's avatar Alexander Rose
Browse files

added combination iterator

parent 7ee3a1f7
No related branches found
No related tags found
No related merge requests found
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { combinations } from '../combination'
describe('Combination', () => {
it('test123-2', () => {
const c = combinations([1, 2, 3], 2)
expect(c).toEqual([[1, 2], [1, 3], [2, 3]]);
});
it('test1234-2', () => {
const c = combinations([1, 2, 3, 4], 2)
expect(c).toEqual([[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]]);
});
it('test1234-1', () => {
const c = combinations([1, 2, 3, 4], 1)
expect(c).toEqual([[1], [2], [3], [4]]);
});
it('test1234-4', () => {
const c = combinations([1, 2, 3, 4], 4)
expect(c).toEqual([[1, 2, 3, 4]]);
});
});
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
// adpated from https://github.com/dankogai/js-combinatorics, MIT 2013-2016 Dan Kogai
import Iterator from '../iterator'
function P(m: number, n: number) {
let p = 1
while (n--) p *= m--
return p
}
function C(m: number, n: number) {
if (n > m) return 0
return P(m, n) / P(n, n)
}
function nextIndex(n: number) {
const smallest = n & -n
const ripple = n + smallest
const newSmallest = ripple & -ripple
const ones = ((newSmallest / smallest) >> 1) - 1
return ripple | ones
};
export class CombinationIterator<T> implements Iterator<T[]> {
private value: T[]
private index: number
private maxIndex: number
size: number
hasNext: boolean = false;
move() {
if (this.hasNext) {
let i = 0, j = 0, n = this.index
for (; n; n >>>= 1, i++) {
if (n & 1) this.value[j++] = this.array[i]
}
this.index = nextIndex(this.index)
this.hasNext = this.index < this.maxIndex
}
return this.value;
}
constructor(private array: T[], count: number) {
this.index = (1 << count) - 1
this.size = C(array.length, count)
this.maxIndex = 1 << array.length,
this.value = new Array(count)
this.hasNext = count > 0 && count <= array.length
}
}
export function combinations<T>(array: T[], count: number): T[][] {
const out: T[][] = []
const combinationIt = new CombinationIterator(array, count)
while (combinationIt.hasNext) out.push(combinationIt.move().slice())
return out
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment