Created
March 27, 2021 07:11
-
-
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
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
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) | |
} | |
} |
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
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