-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathforSubset.ts
97 lines (90 loc) · 2.37 KB
/
forSubset.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* eslint-disable space-in-parens */
function foo() {
// forSubset枚举某个状态的所有子集(子集的子集)
const state = 0b1101
for (let g1 = state; ~g1; g1 = g1 === 0 ? -1 : (g1 - 1) & state) {
if (g1 === state || g1 === 0) continue
const g2 = state ^ g1
console.log(g1.toString(2), g2.toString(2))
}
}
/**
* 升序枚举state所有子集的子集.
* 0b1101 -> 0,1,4,5,8,9,12,13.
*/
function enumerateSubsetOfStateAscending(
state: number,
callback: (subset: number) => void | boolean
): void {
for (let x = 0; ; x = (x - state) & state) {
if (callback(x)) return
if (x === state) break
}
}
/**
* 降序枚举state所有子集的子集.
* 0b1101 -> 13,12,9,8,5,4,1,0.
*/
function enumerateSubsetOfStateDescending(
state: number,
callback: (subset: number) => void | boolean
): void {
for (let x = state; ; x = (x - 1) & state) {
if (callback(x)) return
if (x === 0) break
}
}
/**
* 升序枚举state的所有超集.
* 0b1101 -> 13,15.
*/
function enumerateSupersetOfState(
n: number,
state: number,
callback: (superset: number) => void | boolean
): void {
const upper = 1 << n
for (let x = state; x < upper; x = (x + 1) | state) {
if (callback(x)) return
}
}
/**
* 遍历n个元素的集合中大小为k的子集(combinations).
* 一共有C(n,k)个子集.
* C(4,2) -> 3,5,6,9,10,12.
*/
function enumerateSubsetOfSizeK(
n: number,
k: number,
callback: (subset: number) => void | boolean
): void {
if (k <= 0 || k > n) return
const upper = 1 << n
for (let x = (1 << k) - 1; x < upper; ) {
if (callback(x)) return
const t = x | (x - 1)
// nextCombination (gosper hack)
x = (t + 1) | (((~t & -~t) - 1) >>> (32 - Math.clz32(x & -x)))
}
}
if (require.main === module) {
enumerateSubsetOfStateAscending(0b1101, subset => {
console.log(subset.toString(2))
})
enumerateSubsetOfStateDescending(0b1101, subset => {
console.log(subset.toString(2))
})
enumerateSupersetOfState(4, 0b1101, superset => {
console.log(superset.toString(2))
})
enumerateSubsetOfSizeK(4, 2, subset => {
console.log(subset.toString(2), '999')
})
console.log('ok')
}
export {
enumerateSubsetOfStateAscending,
enumerateSubsetOfStateDescending,
enumerateSubsetOfSizeK,
enumerateSupersetOfState
}