任意の階層だけ繰り返しをネストする(Ruby)

※注
改訂版があります。
任意の階層だけ繰り返しをネストする(Ruby) -- 改訂版 - Camera Obscura


簡単にネストした繰り返しを実行できるようにしました。Integer#times の多重ネスト版です。配列にそれぞれの階層で繰り返す回数を入れます。配列の大きさを変えれば、簡単にどれだけでも深くネストできます。プログラムの中でネストの深さを動的に変えることもできます。

class Array
  def nest_loop(&bk)
    nsloop(self, [], &bk)
  end
  
  private
  def nsloop(ar1, ar2, &bk)
    tmp1 = ar1.dup
    time = tmp1.shift
    unless time
      bk.call(ar2)
    else
      time.times do |i|
        tmp2 = ar2.dup
        tmp2.push(i)
        nsloop(tmp1, tmp2, &bk)
      end
    end
  end
end

実行例。

[4, 2, 3].nest_loop do |i, j, k|
  print "#{[i, j, k]} "
end
#=>
[0, 0, 0] [0, 0, 1] [0, 0, 2]
[0, 1, 0] [0, 1, 1] [0, 1, 2]
[1, 0, 0] [1, 0, 1] [1, 0, 2]
[1, 1, 0] [1, 1, 1] [1, 1, 2]
[2, 0, 0] [2, 0, 1] [2, 0, 2]
[2, 1, 0] [2, 1, 1] [2, 1, 2]
[3, 0, 0] [3, 0, 1] [3, 0, 2]
[3, 1, 0] [3, 1, 1] [3, 1, 2]

これは次のコードと同等です。

4.times do |i|
  2.times do |j|
    3.times do |k|
      print "#{[i, j, k]}"
    end
  end
end