Xavier Jacob - 9 months ago 37
Ruby Question

# How to extract each individual combination from a flat_map?

I'm fairly new to ruby and it's my first question here on stackoverflow so pardon me if I'm being a complete noob.

The code which i am working with contains this line -

``````puts (6..6).flat_map{|n| ('a'..'z').to_a.combination(n).map(&:join)}
``````

What the code does is that its starts printing each of the combinations starting from "abcdef" and continues till the end (which i have never seen as it has 26^6 combinations).

Of course having an array of that size (26^6) is unimaginable hence I was wondering if there is any way by which i can get next combination in a variable, work with it, and then continue on to the next combination ?

For example I calculate the first combination as "abcdef" and store it in a variable 'combo' and use that variable somewhere and then the next combination is calculated and "abcdeg" is stored in 'combo' and hence the loop continues ?

Thanks

`(6..6).flat_map { |n| ... }` doesn't do much. Your code is equivalent to:

``````puts ('a'..'z').to_a.combination(6).map(&:join)
``````

To process the values one by one, you can pass a block to `combination`:

``````('a'..'z').to_a.combination(6) do |combo|
puts combo.join
end
``````

If no block is given, `combination` returns an `Enumerator` that can be iterated by calling `next`:

``````enum = ('a'..'z').to_a.combination(6)
#=> #<Enumerator: ["a", "b", "c", ..., "w", "x", "y", "z"]:combination(6)>

enum.next
#=> ["a", "b", "c", "d", "e", "f"]

enum.next
#=> ["a", "b", "c", "d", "e", "g"]

enum.next
#=> ["a", "b", "c", "d", "e", "h"]
``````

Note that `('a'..'z').to_a.combination(6)` will "only" yield 230,230 combinations:

``````('a'..'z').to_a.combination(6).size
#=> 230230
``````

As opposed to 26 ^ 6 = 308,915,776. You are probably looking for `repeated_permutation`:

``````('a'..'z').to_a.repeated_permutation(6).size
#=> 308915776
``````

Another way to iterate from `"aaaaaa"` to `"zzzzzz"` is a simple range:

``````('aaaaaa'..'zzzzzz').each do |combo|
puts combo
end
``````

Or manually by calling `String#succ`: (this is what `Range#each` does under the hood)

``````'aaaaaa'.succ #=> "aaaaab"
'aaaaab'.succ #=> "aaaaac"

'aaaaaz'.succ #=> "aaaaba"
``````