Skip to content

Instantly share code, notes, and snippets.

@jemmons
Created July 31, 2017 20:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jemmons/d3ca0e29ae3b913ce1c42b21790d807c to your computer and use it in GitHub Desktop.
Save jemmons/d3ca0e29ae3b913ce1c42b21790d807c to your computer and use it in GitHub Desktop.
import Foundation
public struct CartesianProductIterator<X, Y>: IteratorProtocol where X: IteratorProtocol, Y: Collection {
private var xIt: X
private let yCol: Y
private var x: X.Element?
private var yIt: Y.Iterator
public init(xs: X, ys: Y) {
xIt = xs
yCol = ys
x = xIt.next()
yIt = yCol.makeIterator()
}
public typealias Element = (X.Element, Y.Element)
public mutating func next() -> Element? {
guard !yCol.isEmpty else {
return nil
}
guard let someX = x else {
return nil
}
guard let someY = yIt.next() else {
yIt = yCol.makeIterator()
x = xIt.next()
return next()
}
return (someX, someY)
}
}
public struct CartesianProductSequence<X, Y>: Sequence where X: Sequence, Y: Collection {
public typealias Iterator = CartesianProductIterator<X.Iterator, Y>
private let xs: X
private let ys: Y
public init(xs: X, ys: Y) {
self.xs = xs
self.ys = ys
}
public func makeIterator() -> Iterator {
return Iterator(xs: xs.makeIterator(), ys: ys)
}
}
public func product<X, Y>(_ xs: X, _ ys: Y) -> CartesianProductSequence<X, Y> where X: Sequence, Y: Collection {
return CartesianProductSequence(xs: xs, ys: ys)
}
// USAGE:
let xs = 1...10
let ys = ["A", "B", "C", "D", "E",
"F", "G", "H", "I", "J"]
product(xs, ys).forEach { x, y in
print(x)
print(y)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment