Sergey Blohin
Sergey Blohin

Reputation: 620

Optimize nested loops in Ruby

In Ruby I have three nested loops:

array.each do |a|
  array.each do |b|
    array.each do |c|
      puts a * b * c
    end
  end
end

How can I optimize this code, if the number of nested loops can be increased to 5-10 and more iterations?

Example:

array.each do |a|
  array.each do |b|
    array.each do |c|
       array.each do |d|
         array.each do |e|
           array.each do |f|
             puts a * b * c * d * e * f
           end
         end
      end
    end
  end
end

Upvotes: 4

Views: 1448

Answers (2)

spickermann
spickermann

Reputation: 106802

You can do something like this:

array.repeated_combination(array.size).each do |combination| 
  puts combination.reduce(:*)
end

Array#repeated_combination returns an enumerator that yields all possible combinations.

Because this method generates all combinations before printing any output is might take a while depending on the size of the array. Keep in mind that the number of possible combinations increases quite fast: O(nⁿ) with n being the number of elements in the array.

Upvotes: 8

Cary Swoveland
Cary Swoveland

Reputation: 110675

Here are two other ways (though I prefer @spickermann's answer)

#1

array = [1,2,3]
n = 4
arr = array.product(*[array]*(n-1)).map { |arr| arr.reduce(:*) }
arr.size #=> 81 = arr.size**n
arr.each { |e| puts e }
1
2
3
2
4
6
3
6
9
...
54
27
54
81

If you just want to print the products, replace map with each and arr.reduce(:*) with puts arr.reduce(:*).

#2

sz = array.size
(0...sz**n).map { |i| i.to_s(sz)
                       .rjust(n,'_')
                       .chars
                       .reduce(1) { |t,e| t * (e=='_' ? 1 : array[e.to_i]) }
                }

Upvotes: 0

Related Questions