This document covers working with combinatorial iterators in RcppAlgos
. Combinatorial iterators in RcppAlgos
are memory efficient like traditional iterator objects. They allow traversal of combinations/permutations one by one without the necessity for storing all results in memory.
Unlike traditional combinatorial iterators, the iterators in RcppAlgos
offers random access via the [[
operator. This means, we can access the nth lexicographical order result on demand without having to first iterate over the previous n - 1 results.
In order to iterate, we must initialize an iterator via comboIter
or permuteIter
. The interface is very similar to comboGeneral
and permuteGeneral
.
library(RcppAlgos)
## Initialize the iterator
= comboIter(5, 3)
a
## Get the first combination
$nextIter()
a1] 1 2 3
[
## And the next
$nextIter()
a1] 1 2 4
[
## Set the current iterator to a variable
= a$currIter()
iter = 1
i
## Iterate until there are no more
while (!isFALSE(iter)) {
cat(i, " ", iter, "\n")
= a$nextIter()
iter = i + 1
i
}1 1 2 4
2 1 2 5
3 1 3 4
4 1 3 5
5 1 4 5
6 2 3 4
7 2 3 5
8 2 4 5
9 3 4 5
method(s)
No more results. To see the last result, use the prevIter
## See the output of comboGeneral for comparison
comboGeneral(5, 3, lower = 2)
1] [,2] [,3]
[,1,] 1 2 4
[2,] 1 2 5
[3,] 1 3 4
[4,] 1 3 5
[5,] 1 4 5
[6,] 2 3 4
[7,] 2 3 5
[8,] 2 4 5
[9,] 3 4 5
[
## Call the summary method to see information about our iterator
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 11
[
$totalResults
1] 10
[
$totalRemaining
1] -1 [
The standard combinatorial iterators in RcppAlgos
are bidirectional iterators. This means that not only can we iterate in a forward manner (i.e. lexicographically), but we can also iterate backwards (i.e. Reverse Lexicographical Order) via the prevIter
method(s).
## Using the same iterable from the previous section
$currIter()
amethod(s)
No more results. To see the last result, use the prevIter
1] FALSE
[
## As the comment says, we call the prevIter method to see the last result
$prevIter()
a1] 3 4 5
[
## Get the previous result
$prevIter()
a1] 2 4 5
[
## As in the previous example, we set the current iterator to a variable
= a$currIter()
iter
## Defined above
print(i)
1] 10
[
## Iterate until we are at the very beginning. Note that the
## output is exactly the same as above, but in reverse order
while (!isFALSE(iter)) {
= i - 1
i cat(i, " ", iter, "\n")
= a$prevIter()
iter
}9 2 4 5
8 2 3 5
7 2 3 4
6 1 4 5
5 1 3 5
4 1 3 4
3 1 2 5
2 1 2 4
1 1 2 3
method(s)
Iterator Initialized. To see the first result, use the nextIter
## Call the summary method to see information about our iterator
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 0
[
$totalResults
1] 10
[
$totalRemaining
1] 10 [
There are four methods which allow for obtaining more than one result at a time: nextNIter
, prevNIter
, nextRemaining
, and prevRemaining
.
## Reset the iterator
$startOver
a
## Get the next 4 combinations
$nextNIter(4)
a1] [,2] [,3]
[,1,] 1 2 3
[2,] 1 2 4
[3,] 1 2 5
[4,] 1 3 4
[
## Get the summary. Note that the index has been updated
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 4
[
$totalResults
1] 10
[
$totalRemaining
1] 6
[
## View the current combination
$currIter()
a1] 1 3 4
[
## Get the remaining combinations with nextRemaining
$nextRemaining()
a1] [,2] [,3]
[,1,] 1 3 5
[2,] 1 4 5
[3,] 2 3 4
[4,] 2 3 5
[5,] 2 4 5
[6,] 3 4 5
[
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 11
[
$totalResults
1] 10
[
$totalRemaining
1] -1 [
Now, we look at the opposite direction.
## Get the previous 4 combinations
$prevNIter(4)
a1] [,2] [,3]
[,1,] 3 4 5
[2,] 2 4 5
[3,] 2 3 5
[4,] 2 3 4
[
## Get the summary. Note that the index has been updated
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 7
[
$totalResults
1] 10
[
$totalRemaining
1] 3
[
## View the current combination
$currIter()
a1] 2 3 4
[
## Get the remaining previous combinations with prevRemaining
$prevRemaining()
a1] [,2] [,3]
[,1,] 1 4 5
[2,] 1 3 5
[3,] 1 3 4
[4,] 1 2 5
[5,] 1 2 4
[6,] 1 2 3
[
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 0
[
$totalResults
1] 10
[
$totalRemaining
1] 10 [
For standard combinatorial iterators in RcppAlgos
, we can jump to the nth combination/permutation without the need for iterating over the first n - 1 results.
## Reset the iterator
$startOver()
a
## How many total combinations do we have?
$summary()$totalResults
a1] 10
[
## Let's get the 3rd combination
3]]
a[[1] 1 2 5
[
## See the summary. Note that the index has been updated
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 3
[
$totalResults
1] 10
[
$totalRemaining
1] 7
[
## Let's see the 9th combination
9]]
a[[1] 2 4 5
[
## What about the first and last combination?
$front()
a1] 1 2 3
[
$back()
a1] 3 4 5
[
## Again the index has been updated
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 10
[
$totalResults
1] 10
[
$totalRemaining
1] 0
[
$currIter()
a1] 3 4 5 [
We can also easily return a random sample of combinations with the [[
operator by passing a vector of indices. In these cases, it should be noted that the current index will not be updated.
## Set the current index to the second combination
2]]
a[[1] 1 2 4
[
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 2
[
$totalResults
1] 10
[
$totalRemaining
1] 8
[
set.seed(121)
= sample(a$summary()$totalResults, 4)
samp
samp1] 4 7 10 1
[
a[[samp]]1] [,2] [,3]
[,1,] 1 3 4
[2,] 2 3 4
[3,] 3 4 5
[4,] 1 2 3
[
## Note that the current index remains unchanged
$summary()
a$description
1] "Combinations of 5 choose 3"
[
$currentIndex
1] 2
[
$totalResults
1] 10
[
$totalRemaining
1] 8 [
Just as with comboGeneral
and permuteGeneral
, we can pass a user defined function to comboIter
and permuteIter
.
## Initialize the iterator
= permuteIter(LETTERS[1:4], 3, FUN = function(p) paste(p, collapse = ""))
b
$nextIter()
b1] "ABC"
[
$nextNIter(5)
b1]]
[[1] "ABD"
[
2]]
[[1] "ACB"
[
3]]
[[1] "ACD"
[
4]]
[[1] "ADB"
[
5]]
[[1] "ADC"
[
$back()
b1] "DCB"
[
$summary()
b$description
1] "Permutations of 4 choose 3"
[
$currentIndex
1] 24
[
$totalResults
1] 24
[
$totalRemaining
1] 0
[
$prevIter()
b1] "DCA"
[
$prevNIter(5)
b1]]
[[1] "DBC"
[
2]]
[[1] "DBA"
[
3]]
[[1] "DAC"
[
4]]
[[1] "DAB"
[
5]]
[[1] "CDB"
[
$nextRemaining()
b1]]
[[1] "DAB"
[
2]]
[[1] "DAC"
[
3]]
[[1] "DBA"
[
4]]
[[1] "DBC"
[
5]]
[[1] "DCA"
[
6]]
[[1] "DCB"
[
## Random access
5]]
a[[1] "ADB"
[
$prevRemaining()
b1]]
[[1] "ACD"
[
2]]
[[1] "ACB"
[
3]]
[[1] "ABD"
[
4]]
[[1] "ABC"
[
## View the source vector
$sourceVector()
b1] "A" "B" "C" "D" [