[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to give depth to arrays?

Chris Morales

11/22/2007 5:25:00 AM

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

12 Answers

Shuaib Zahda

11/22/2007 6:21:00 AM

0

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

Peter Szinek

11/22/2007 7:39:00 AM

0

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.rubyra...
http://s...



Chris Morales

11/22/2007 8:06:00 AM

0

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

Chris Morales

11/22/2007 9:28:00 AM

0

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

Jesús Gabriel y Galán

11/22/2007 2:03:00 PM

0

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.

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.

Jesús Gabriel y Galán

11/22/2007 4:49:00 PM

0

On Nov 22, 2007 3:03 PM, Jes=FAs Gabriel y Gal=E1n <jgabrielygalan@gmail.co=
m> wrote:
> On Nov 22, 2007 10:28 AM, Chris Morales <primo.tertio@gmail.com> wrote:
> > p [2,3,3,5,4,4].depthen =3D> [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 # =3D> [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...

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 =3D self[0]
result =3D []
stack =3D []
current =3D result
each do |x|
case depth <=3D> x
when 0
current << x
when -1
diff =3D x - depth
value =3D [x]
tmp =3D value
(diff - 1).times do
value =3D [value]
stack.push value
end
current << value
current =3D tmp
stack.push current
when 1
diff =3D depth - x + 1
diff.times {current =3D stack.pop}
current =3D result if current.nil?
current << x
end
depth =3D x
end
result
end
end


a =3D [[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.

Eric I.

11/22/2007 6:29:00 PM

0

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://Lea...

Sebastian Hungerecker

11/22/2007 6:39:00 PM

0

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

Eric I.

11/22/2007 6:47:00 PM

0

On Nov 22, 1:39 pm, Sebastian Hungerecker <sep...@googlemail.com>
wrote:
> quoth Chris Morales:
>
> >>>> the first number is the base depth

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

====

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

Jesús Gabriel y Galán

11/22/2007 6:59:00 PM

0

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

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.