Skip to content

Instantly share code, notes, and snippets.

@icedraco
Last active February 7, 2018 15:30
Show Gist options
  • Save icedraco/b23498d474556e9f7a30975847229c3b to your computer and use it in GitHub Desktop.
Save icedraco/b23498d474556e9f7a30975847229c3b to your computer and use it in GitHub Desktop.
Cartesian product of multiple iterables as a sequence
/* Created by IceDragon on 06-Feb-2018 */
import kotlin.coroutines.experimental.buildSequence
fun product(vararg lists: Iterable<Any?>): Sequence<List<Any?>> = buildSequence {
if (lists.isEmpty())
return@buildSequence // no combinations
val iterators = Array(lists.size, { i -> lists[i].iterator() })
if (iterators.any { !it.hasNext() })
return@buildSequence // no combinations available if one of the iterables is empty
val accumulator = Array<Any?>(lists.size, { null })
var index = 0
while (index >= 0) {
if (index >= lists.size) {
yield(accumulator.toList()) // <-- return a combination
index--
} else {
if (iterators[index].hasNext()) {
accumulator[index] = iterators[index].next()
index++
} else {
iterators[index] = lists[index].iterator()
index--
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment