Dynamic nested each in ruby 1.8.7?

How can one have a function that uses a dynamic amount of each
statements? Below is the code for level 3. Is there a way to define this
easily using recursion? I want to avoid having a separate function for
each level.

def calc nums, level
tmp = []
nums.each{ |n| tmp.push n
nums.each{ |n2| tmp.push n+n2
nums.each{ |n3| tmp.push n+n2+n3
}}}
tmp
end

puts calc([“0”, “1”], 3)

Wow,

what are you trying to accomplish? Permutations maybe?

I can think of some solutions for dynamical nested each-statments, but
I frankly can’t think of a problem that I would solve using them.

Regards,
Florian G.

On Oct 18, 2009, at 12:13 AM, Toi T. wrote:

 nums.each{ |n3| tmp.push n+n2+n3
 }}}

tmp
end

puts calc([“0”, “1”], 3)

Posted via http://www.ruby-forum.com/.


Florian G.

smtp: [email protected]
jabber: [email protected]
gpg: 533148E2

On Sun, Oct 18, 2009 at 11:43 AM, Toi T. [email protected] wrote:

 }}}

tmp
end

puts calc([“0”, “1”], 3)

Does this give you the right output?
No recursion, but…

def calc(n, v)
h,t = Hash[*(0…n.size).zip(n).flatten],[]
(1…v).each{|x| (0…n.size**x).each{|y| t <<
y.to_s(n.size).rjust(x,“0”)}}
t.map{|a| a.split(//).map{|b| h[b.to_i]}.join}.sort
end

p calc([“0”,“1”], 3)

Harry

That function does not give the correct output for larger arrays. The
level functions can be generated with eval, see the code below. However
there must be a better Ruby way.

def calc level
tmp = [“def calcd nums\ntmp=[]\n”]
str = “n1”
num = 1

level.times {
tmp.push “nums.each{ |n#{num}| tmp.push #{str}\n”
str = str+" + n#{num+=1}"
}
level.times { tmp.push “}”}

tmp.push “\ntmp\n”
tmp.push “end”
tmp.to_s
end
array, times = (‘1’…‘10’).to_a, 3
eval(calc(times))
p calcd(array)

Harry K. wrote:

On Sun, Oct 18, 2009 at 11:43 AM, Toi T. [email protected] wrote:

 }}}

tmp
end

puts calc([“0”, “1”], 3)

Does this give you the right output?
No recursion, but…

def calc(n, v)
h,t = Hash[*(0…n.size).zip(n).flatten],[]
(1…v).each{|x| (0…n.size**x).each{|y| t <<
y.to_s(n.size).rjust(x,“0”)}}
t.map{|a| a.split(//).map{|b| h[b.to_i]}.join}.sort
end

p calc([“0”,“1”], 3)

Harry

On Mon, Oct 19, 2009 at 8:00 AM, Harry K. [email protected]
wrote:

p calc_new((1…10).to_a, 3)

Not always correct.
Hmmmmm…

On Mon, Oct 19, 2009 at 6:46 AM, Toi T. [email protected] wrote:

tmp.push “nums.each{ |n#{num}| tmp.push #{str}\n”
p calcd(array)

def calc_new(arr,l)
h,t = Hash[*(0…arr.size).zip(arr).flatten],[]
(1…l).each do |z|
(0…arr.size**l).each do |x|
t << x.to_s(arr.size).rjust(z,“0”)
end
end
t.uniq.sort.map{|c| c.split(//).map{|d| h[d.to_i]}.join}
end

p calc_new((1…10).to_a, 3)

Harry

On Sun, Oct 18, 2009 at 11:43 AM, Toi T. [email protected] wrote:

 }}}

tmp
end

puts calc([“0”, “1”], 3)

I think this will do it if your array size <= 36

def calc_new(arr,l)
h,t = Hash[*(0…arr.size).zip(arr).flatten],[]
p h
(1…l).each do |z|
(0…arr.size**l).each do |x|
t << x.to_s(arr.size).rjust(z,“0”)
end
end
t.uniq.sort.map{|c| c.split(//).map{|d| h[d.to_i(arr.size)]}.join}
end

p calc_new((1…12).to_a, 3)

Harry

I think this will do it if your array size <= 36

Harry

That code does work well for array.size <= 36, however I need a dynamic
amount without an arbitrary limitation.

The data set causes an illegal radix ArgumentError since it is indeed >
36. Using eval any array size can be handled. I may just use Java if a
robust solution is not possible in Ruby without resorting to eval.

Toi T. wrote:

def calc nums, level
tmp = []
nums.each{ |n| tmp.push n
nums.each{ |n2| tmp.push n+n2
nums.each{ |n3| tmp.push n+n2+n3
}}}
tmp
end

puts calc([“0”, “1”], 3)

Look at Array#enumeration in my ISC-licensed combinatorics library:
http://github.com/sunaku/inochi/blob/master/lib/inochi/util/combo.rb

With that library, your question can be answered as follows:

[email protected] ~/s/inochi> irb -r pp -r lib/inochi/util/combo.rb

ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]

pp [“0”, “1”].enumeration(3)
[[“0”, “0”, “0”],
[“0”, “0”, “1”],
[“0”, “1”, “0”],
[“0”, “1”, “1”],
[“1”, “0”, “0”],
[“1”, “0”, “1”],
[“1”, “1”, “0”],
[“1”, “1”, “1”]]
=> nil

Florian G. wrote:

what are you trying to accomplish? Permutations maybe?
I frankly can’t think of a problem that I would solve using them.

One application is exhaustive, brute-force unit testing. For example,
in my eRuby processor, it was necessary to test proper handling of
eRuby directives surrounded by various amounts and kinds of whitespace
(empty string, spaces, tabs, and line breaks):

http://github.com/sunaku/ember/blob/master/test/ember/template.rb

Suraj K. wrote:

Florian G. wrote:

what are you trying to accomplish? Permutations maybe?
I frankly can’t think of a problem that I would solve using them.

One application is exhaustive, brute-force unit testing. For example,
in my eRuby processor, it was necessary to test proper handling of
eRuby directives surrounded by various amounts and kinds of whitespace
(empty string, spaces, tabs, and line breaks):

http://github.com/sunaku/ember/blob/master/test/ember/template.rb

My jaw is gaping at the code I read…
Would this help at all?
http://trevoke.net/blog/2008/12/20/lexicographic-permutations-in-ruby/

Aldric G. wrote:

Suraj K. wrote:

Look at Array#enumeration in my ISC-licensed combinatorics library:
http://github.com/sunaku/inochi/blob/master/lib/inochi/util/combo.rb

My jaw is gaping at the code I read…

:slight_smile: To be fair, my library also implements combinations and
enumerations: both in the “n choose k” subset form and in the exhaustive
“all items in this list” form.

It’s interesting to note that the only algorithmic difference between
permutations and combinations is that combinations prevent already
visited vertices from being visited again in subsequent iterations,
whereas permutations do not. I was quite pleased with this observation,
because it allowed me to base nPk and nCk on a single implementation:
pnk_cnk_impl().

Would this help at all?
http://trevoke.net/blog/2008/12/20/lexicographic-permutations-in-ruby/

I did not understand how to use that simpler permutations() method:

[email protected] ~> irb

ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]

def permutations li
if li.length < 2
yield li
else
?> li.each do |element|
?> permutations(li.select() {|n| n != element})
?> {|val| yield([element].concat val)}

  end
end

end
=> nil

permutations [“0”, “1”]
LocalJumpError: no block given
from (irb):7:in permutations' from (irb):3:inpermutations’
from (irb):6:in permutations' from (irb):5:ineach’
from (irb):5:in `permutations’
from (irb):12

permutations [“0”, “1”] do end
=> [“0”, “1”]

permutations [“0”, “1”] do |val| val end
=> [“0”, “1”]

permutations [“0”, “1”, “2”] do end
=> [“0”, “1”, “2”]

permutations [“0”, “1”, “2”] do |val| val end
=> [“0”, “1”, “2”]

permutations [“0”, “1”, “2”] do |val| [val] end
=> [“0”, “1”, “2”]

Any suggestions?

Suraj K. wrote:

Aldric G. wrote:

Would this help at all?
http://trevoke.net/blog/2008/12/20/lexicographic-permutations-in-ruby/

I did not understand how to use that simpler permutations() method:
Any suggestions?

Never mind, I figured it out:

result = []
=> []

permutations [“0”, “1”, “2”] do |val| result << val end
=> [“0”, “1”, “2”]

pp result
[[“0”, “1”, “2”],
[“0”, “2”, “1”],
[“1”, “0”, “2”],
[“1”, “2”, “0”],
[“2”, “0”, “1”],
[“2”, “1”, “0”]]
=> nil

Pretty cool. An improvement would be to return an Enumerator.

On Oct 19, 2009, at 3:14 PM, Suraj K. wrote:

Pretty cool. An improvement would be to return an Enumerator.

How about:

module Enumerable
def permutations
return enum_for(:permutations) unless block_given?

 if length < 2
   yield self
 else
   each do |element|
     select { |candidate|
       candidate != element
     }.permutations { |smaller|
       yield [element, *smaller]
     }
   end
 end

end
end

[1,2,3].permutations { |x| p x }

p [1,2,3].permutations.map { |x| x.reverse }

Gary W.

Suraj K. wrote:

Look at Array#enumeration in my ISC-licensed combinatorics library:
http://github.com/sunaku/inochi/blob/master/lib/inochi/util/combo.rb

Thank you! That method is what I needed.