Skip to content

Instantly share code, notes, and snippets.

@adi-li
Created March 27, 2021 07:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adi-li/9589867552019436453afef39f190366 to your computer and use it in GitHub Desktop.
Save adi-li/9589867552019436453afef39f190366 to your computer and use it in GitHub Desktop.
Iterating all possible combinations of r elements in a given array of objects in Swift
class Combinator<Object>: IteratorProtocol {
typealias Element = [Object]
var objects: [Object]
var numberOfSelection: Int
private var currentIndexes: [Int]
private var done = false
func next() -> [Object]? {
guard !currentIndexes.isEmpty else { return nil }
guard objects.count > numberOfSelection else {
currentIndexes.removeAll()
return objects
}
guard currentIndexes.last != nil, currentIndexes.last! >= objects.endIndex else {
return currentObjectsAndIncreaseIndex()
}
currentIndexes.popLast()
increaseLastIndex()
while let last = currentIndexes.last, last >= objects.endIndex - (numberOfSelection - currentIndexes.count) {
currentIndexes.popLast()
increaseLastIndex()
}
guard !currentIndexes.isEmpty else { return nil }
while currentIndexes.count < numberOfSelection {
currentIndexes.append((currentIndexes.last ?? -1) + 1)
}
return currentObjectsAndIncreaseIndex()
}
private func currentObjectsAndIncreaseIndex() -> [Object] {
let objs = currentIndexes.map { objects[$0] }
increaseLastIndex()
return objs
}
private func increaseLastIndex() {
guard currentIndexes.count > 0 else { return }
currentIndexes[currentIndexes.endIndex - 1] += 1
}
init(_ objects: [Object], _ numberOfSelection: Int) {
self.objects = objects
self.numberOfSelection = numberOfSelection
guard numberOfSelection > 0, !objects.isEmpty else {
currentIndexes = []
return
}
currentIndexes = Array(0..<numberOfSelection)
}
}
let c = Combinator(["A", "K", "Q", "J", "T", "9", "8"], 5)
while let i = c.next() {
print("\(i)")
}
/*
Print Result:
["A", "K", "Q", "J", "T"]
["A", "K", "Q", "J", "9"]
["A", "K", "Q", "J", "8"]
["A", "K", "Q", "T", "9"]
["A", "K", "Q", "T", "8"]
["A", "K", "Q", "9", "8"]
["A", "K", "J", "T", "9"]
["A", "K", "J", "T", "8"]
["A", "K", "J", "9", "8"]
["A", "K", "T", "9", "8"]
["A", "Q", "J", "T", "9"]
["A", "Q", "J", "T", "8"]
["A", "Q", "J", "9", "8"]
["A", "Q", "T", "9", "8"]
["A", "J", "T", "9", "8"]
["K", "Q", "J", "T", "9"]
["K", "Q", "J", "T", "8"]
["K", "Q", "J", "9", "8"]
["K", "Q", "T", "9", "8"]
["K", "J", "T", "9", "8"]
["Q", "J", "T", "9", "8"]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment