-
Notifications
You must be signed in to change notification settings - Fork 0
/
powerset.js
64 lines (61 loc) · 1.58 KB
/
powerset.js
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
function* powerSet(s) {
// s is a Set
// power set of empty set is the set containing the empty set. eg P({}) = {{}}
// the power set of any other set is all the subsets of the set containing some specific element and all the subsets of the set not containing that specific element
if(s === null)
throw Error("Null parameter")
if(s.size === 0) {
let empty = new Set()
empty.add(new Set())
return empty
}
// P(s) = P(T) union f(e, P(T)) where f(e,T) = {X union e | X in T}
for(let item of s) {
let T = new Set(s)
T.delete(item)
console.log("Into pset(): " + Array.from(T) + " item: " + item)
yield* powerSet(T)
for(let ss of powerSet(T)) {
console.log("Add: " + item + " to set: " + ss)
yield ss.add(item)
}
}
}
function* pSet(s) {
yield* chain(range(s.size+1).map(l => combination(s, l)))
}
function* chain(iter) {
for(let it of iter) {
for(let i of it)
yield i
}
}
function range(start, stop=0, step=1) {
if(stop === 0)
[start, stop] = [stop, start]
return [...new Array(Math.floor((stop-start)/step)).keys()].map(i=> i*step+start)
}
function* combination(iter, r) {
let pool = Array.from(iter)
let n = pool.length
if(r > n)
return
let indices = range(r)
yield pool.slice(0,r)
while(true) {
let found = false
for(var i of range(r).reverse()) {
if(indices[i] != i + n - r) {
found = true
break
}
}
if(!found)
return
indices[i] += 1
for(let j of range(i+1, r)) {
indices[j] = indices[j-1] + 1
}
yield indices.map(k => pool[k])
}
}