How to give depth to arrays?

Hi,

I'm trying to convert an array like [2,3,3,5,4,4] in
[2,[3,3,[[5],4,4]]], but I really can't figure how to this.
Is there any way to achieve this in Ruby?

Thanks in advance.

···

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

Chris Morales wrote:

Hi,

I'm trying to convert an array like [2,3,3,5,4,4] in
[2,[3,3,[[5],4,4]]], but I really can't figure how to this.
Is there any way to achieve this in Ruby?

Thanks in advance.

I once asked a question about multidimensional arrays and I received a
solution like this

irb(main):001:0> array =
=>
irb(main):002:0> new_array = [1,2,3]
=> [1, 2, 3]
irb(main):003:0> array << new_array
=> [[1, 2, 3]]
irb(main):004:0> array << 3
=> [[1, 2, 3], 3]
irb(main):005:0> array[0] << 5
=> [1, 2, 3, 5]
irb(main):006:0> array
=> [[1, 2, 3, 5], 3]
irb(main):007:0> array[0] << [5]
=> [1, 2, 3, 5, [5]]
irb(main):008:0> array
=> [[1, 2, 3, 5, [5]], 3]
irb(main):009:0>

I wish this helps
regards

···

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

Chris Morales wrote:

Hi,

I'm trying to convert an array like [2,3,3,5,4,4] in
[2,[3,3,[[5],4,4]]], but I really can't figure how to this.
Is there any way to achieve this in Ruby?

I don't really get the question... do you want to do this automatically?
If yes, how should the mapping look like (i.e. what decides that 3 is 1 level deep, 5 is 4 level deep etc.)?

Cheers,
Peter

···

___
http://www.rubyrailways.com
http://scrubyt.org

I don't really get the question... do you want to do this automatically?
If yes, how should the mapping look like (i.e. what decides that 3 is 1
level deep, 5 is 4 level deep etc.)?

Sorry, my question was missing some important details.
1/ it's array of numbers only
2/ the first number is the base depth
3/ for every number increase a depth of array is added
   so [1,2,4,2] => [1,[2,[[4]],2]]
   and [5,5,6] => [5,5,[6]]
4/ and it would be wonderful if it were automatic, by extending the
Array class if possible. The image is a kind of opposite of flatten.

for now I'm trying with the insert/slice! couple, no cute at all & not
really working

class Array
  def depthen
    base_depth = self[0]
    range = [0,0]
    in_flag, out_flag = false, false
    self.each_index{ |i|
      if self[i]>base_depth && !in_flag
        in_flag = true;
        range[0] = i
      end
      if self[i] <= base_depth && !out_flag
        out_flag = true
        range[1] = i-1
      end
    }
    self.insert(range[0], self.slice!(eval(range.join('..'))) )
  end
end

p [2,3,3,5,4,4].depthen => [2,[3,3,5,4,4]]

I hope I'm on the good way, but the code is *really* ugly

Thank you in advance,
Chris.

···

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

Okay, I made it kinda works, clunky and ugly though...

class Array
  def max
    max = 0;
    self.each{ |i| max = i>max ? i : max }
    max
  end
  def min
    min = 9999;
    self.each{ |i| min = i<min ? i : min }
    min
  end
  def depthen
    base_depth = self.min
    range = [0,0]
    in_flag, out_flag = false, false
    self.each_index{ |i|
      if self[i]>base_depth && !in_flag
        in_flag = true;
        range[0] = i
      end
      if self[i] <= base_depth && !out_flag
        out_flag = true
        range[1] = i-1
      end
    }
    to_insert = self.slice!(eval(range.join('..')))
    to_insert.depthen if to_insert.max>to_insert.min
    self.insert( range[0], to_insert )
  end
end

p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]

I will be really thankful if anybody could help me improve this monster
with nice ruby tricks.

Thank you in advance,
Chris.

···

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

With your code:

[2,3,5,3].depthen # => [2, [3, [[5], 3]]]

Shouldn't this be:

[2, [3, [[5]], 3]]

?

I'm trying to think of an elegant solution, but I'm kind of slow today...

Jesus.

···

On Nov 22, 2007 10:28 AM, Chris Morales <primo.tertio@gmail.com> wrote:

Okay, I made it kinda works, clunky and ugly though...

class Array
  def max
    max = 0;
    self.each{ |i| max = i>max ? i : max }
    max
  end
  def min
    min = 9999;
    self.each{ |i| min = i<min ? i : min }
    min
  end
  def depthen
    base_depth = self.min
    range = [0,0]
    in_flag, out_flag = false, false
    self.each_index{ |i|
      if self[i]>base_depth && !in_flag
        in_flag = true;
        range[0] = i
      end
      if self[i] <= base_depth && !out_flag
        out_flag = true
        range[1] = i-1
      end
    }
    to_insert = self.slice!(eval(range.join('..')))
    to_insert.depthen if to_insert.max>to_insert.min
    self.insert( range[0], to_insert )
  end
end

p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]

I will be really thankful if anybody could help me improve this monster
with nice ruby tricks.

I will be really thankful if anybody could help me improve this monster
with nice ruby tricks.

My first impression is that the code should probably achieve its goals
in some other way than it's currently attempting. Trying something
this intricate often means setting yourself up for failure. It might
be possible to use trees or something similar instead, depending on
the nature of the problem you've decided to solve.

···

--
Giles Bowkett

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com

I managed to get some time at work and this is my first try,
I use a stack to maintain the arrays for each level when you are
going upwards, so you can add to the same array when you go
downwards (makes any sense?):

class Array
        def depthen
                depth = self[0]
                result =
                stack =
                current = result
                each do |x|
                case depth <=> x
                when 0
                        current << x
                when -1
                        diff = x - depth
                        value =
                        tmp = value
                        (diff - 1).times do
                                value = [value]
                                stack.push value
                        end
                        current << value
                        current = tmp
                        stack.push current
                when 1
                        diff = depth - x + 1
                        diff.times {current = stack.pop}
                        current = result if current.nil?
                        current << x
                end
                depth = x
                end
                result
        end
end

a = [[2,3,3,4,5,4,4], [2,3,5,3, 2]]
a.each {|x| p x.depthen}

[2, [3, 3, [4, [5], 4, 4]]]
[2, [3, [[5]], 3], 2]

Have fun,

Jesus.

···

On Nov 22, 2007 3:03 PM, Jesús Gabriel y Galán <jgabrielygalan@gmail.com> wrote:

On Nov 22, 2007 10:28 AM, Chris Morales <primo.tertio@gmail.com> wrote:
> p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]
>
> I will be really thankful if anybody could help me improve this monster
> with nice ruby tricks.

With your code:

[2,3,5,3].depthen # => [2, [3, [[5], 3]]]

Shouldn't this be:

[2, [3, [[5]], 3]]

?

I'm trying to think of an elegant solution, but I'm kind of slow today...

Others, including Chris Morales, have interpreted the task as follows:

p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]

But that doesn't seem right to me, since the element 2 is at a depth
of 1 and not 2. I would think the result should be:

     [[2,[3,3,[[5],4,4]]]]

Anyway, here's a solution which handles my interpretation:

class Array
  def depthen
    result =

    self.each do |depth|
      array_end = result
      (depth - 1).times do
        array_end << unless array_end.last.kind_of? Array
        array_end = array_end.last
      end
      array_end << depth
    end

    result
  end
end

And here's what it does:

p [2, 3, 3, 5, 4, 1, 4, 6, 10, 2].depthen
  # => [[2, [3, 3, [[5], 4]]], 1, [[[4, [[6, [[[[10]]]]]]]], 2]]

To change it to the other interpretation, just change "depth - 1" to
"depth - 2". And then, presumably, the array depthen is called on
shouldn't have any "1"s in it (although even they're handled
"gracefully" with the depthen method provided).

Eric

···

====

Are you interested in on-site Ruby training that uses well-designed,
real-world, hands-on exercises? http://LearnRuby.com

Eric I. wrote:

Others, including Chris Morales, have interpreted the task as follows:
> p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]

But that doesn't seem right to me, since the element 2 is at a depth
of 1 and not 2.

quoth Chris Morales:

···

the first number is the base depth

--
NP: Moonsorrow - 1065: Aika
Jabber: sepp2k@jabber.org
ICQ: 205544826

Thank you, Sebastian! I lost track of that.

OK, here we go, then:

class Array
  def depthen
    base_depth = first
    result =

    each do |depth|
      array_end = result
      (depth - base_depth).times do
        array_end << unless array_end.last.kind_of? Array
        array_end = array_end.last
      end
      array_end << depth
    end

    result
  end
end

Eric

···

On Nov 22, 1:39 pm, Sebastian Hungerecker <sep...@googlemail.com> wrote:

quoth Chris Morales:

>>>> the first number is the base depth

====

Interested in hands-on, on-site Ruby training? See http://LearnRuby.com
for information about a well-reviewed class.

Yes, that's what I based my solution on. Afterwards I saw in his
solution that he used the min of the array which makes more sense...

Jesus.

···

On Nov 22, 2007 7:39 PM, Sebastian Hungerecker <sepp2k@googlemail.com> wrote:

Eric I. wrote:
> Others, including Chris Morales, have interpreted the task as follows:
> > p [2,3,3,5,4,4].depthen => [2,[3,3,[[5],4,4]]]
>
> But that doesn't seem right to me, since the element 2 is at a depth
> of 1 and not 2.

quoth Chris Morales:

>>>> the first number is the base depth

Wow!
Thanks everybody & Thank you so much Eric

class Array
  def depthen
    base_depth = first
    result =

    each do |depth|
      array_end = result
      (depth - base_depth).times do
        array_end << unless array_end.last.kind_of? Array
        array_end = array_end.last
      end
      array_end << depth
    end

    result
  end
end

I couldn't have dreamt a shorter way to achieve this, You really are a
Genius.
So short and nice! This must be what they call the ruby way I think :wink:

Chris.

···

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