Skip to content

Instantly share code, notes, and snippets.

@vladignatyev
Created March 1, 2020 17:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vladignatyev/7e9399930cb614d6251a4f82b8e75ff1 to your computer and use it in GitHub Desktop.
Save vladignatyev/7e9399930cb614d6251a4f82b8e75ff1 to your computer and use it in GitHub Desktop.
Combinatorics: Pure Swift 5 Power Set algorithm implementation. Returns power set elements (permutation), in ascending order from smaller to bigger subsets.
import Foundation
class PowerSetIterator<T> {
var sourceSet: [T]
var l: Int
var setlen: Int
var ones: [Int]
var lastDigit: Int?
var yield1: Bool
var yield2: Bool
var whileLoop: Bool
init(sourceSet: [T]) {
self.sourceSet = sourceSet
self.l = sourceSet.count
self.setlen = 1
self.ones = []
self.lastDigit = nil
self.yield1 = false
self.yield2 = false
self.whileLoop = false
}
func product() -> [T] {
var result: [T] = []
for i in 0...self.ones.count - 1 {
result.append(self.sourceSet[self.ones[i]])
}
return result
}
func mostSignificant() -> Int {
var k = self.ones.count - 1
while k > -1 && (self.ones[k] == (self.l - 1) - ((self.ones.count) - 1 - k)) {
k -= 1
}
return k
}
func next() -> [T]? {
if !self.yield1 {
self.yield1 = true
return []
}
if !self.yield2 {
self.yield2 = true
self.ones = Array(0...self.setlen - 1)
return self.product()
}
if self.setlen == self.l {
return nil
}
if self.yield2 {
self.lastDigit = self.setlen - 1
self.whileLoop = true
}
guard let lastDigit = self.lastDigit else {
return nil
}
if self.whileLoop {
self.ones[lastDigit] += 1
if self.ones[lastDigit] > self.l - 1 {
self.ones[lastDigit] = self.l - 1
let k = self.mostSignificant()
if k == -1 {
self.whileLoop = false
}
else {
self.ones[k] += 1
if self.setlen > k + 1 {
for i in k + 1...self.setlen - 1 {
self.ones[i] = self.ones[i-1] + 1
}
}
}
}
if self.whileLoop {
return self.product()
}
else {
self.setlen = self.setlen + 1
self.yield2 = false
self.whileLoop = false
return self.next()
}
} else {
return nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment