Created
March 1, 2020 17:16
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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