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)

···

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

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 Gilcher

···

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

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)
--
Posted via http://www.ruby-forum.com/\.

--
Florian Gilcher

smtp: flo@andersground.net
jabber: Skade@jabber.ccc.de
gpg: 533148E2

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 Sun, Oct 18, 2009 at 11:43 AM, Toi Toi <toi@mailinator.com> wrote:

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)
--

--
A Look into Japanese Ruby List in English

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

···

On Sun, Oct 18, 2009 at 11:43 AM, Toi Toi <toi@mailinator.com> wrote:

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)
--

--
A Look into Japanese Ruby List in English

Toi Toi 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:

sun@yantram ~/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

···

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

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 Kakueki wrote:

···

On Sun, Oct 18, 2009 at 11:43 AM, Toi Toi <toi@mailinator.com> 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

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

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.

···

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

Florian Gilcher 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

···

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

Suraj Kurapati 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.

···

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

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 Mon, Oct 19, 2009 at 6:46 AM, Toi Toi <toi@mailinator.com> wrote:

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)

--
A Look into Japanese Ruby List in English

Suraj Kurapati wrote:

Florian Gilcher 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/

···

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

Not always correct.
Hmmmmm.....

···

On Mon, Oct 19, 2009 at 8:00 AM, Harry Kakueki <list.push@gmail.com> wrote:

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)

--
A Look into Japanese Ruby List in English

Aldric Giacomoni wrote:

Suraj Kurapati 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:

skurapati@skurapati-dt ~> 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:in `permutations'
  from (irb):6:in `permutations'
  from (irb):5:in `each'
  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?

···

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

Suraj Kurapati wrote:

Aldric Giacomoni 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.

···

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

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 Wright

···

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

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