Velocity Reviews > Ruby > Control Structures

# Control Structures

Trent Jones
Guest
Posts: n/a

 12-01-2008
G'day all, I'm new to Ruby, been studying Software Engineering at
university and they have been teaching in Java.

As such, I'm trying to learn as few of the basics by going through and
comverting smoe of the programs I made into Ruby. At the moment, I'm
struggling a bit with the control structures, if-then-else is fine,
switch/case is fine. I'm just a little confused about the for and
while/dowhile loops.

I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
array of 'x' length and then fill it with random numbers, then check to
see if those numbers are in order, if not, repeat the process. More or
less anyway.

At the moment I'm using this loop to fill the array:
for num in (0..Integer(a))
monkey[num]=Integer(rand*5+1)
end
variable 'a' is input by the user to determine how big a sequence, i.e.
5 numbers in a row.

Is this the easiest way of doing things?
And then I could use a similar loop to go through and check to see if
each number is in order, but again, is there a simpler way to check?

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

Jakub Pavlík jn.
Guest
Posts: n/a

 12-01-2008
> G'day all, I'm new to Ruby, been studying Software Engineering at
> university and they have been teaching in Java.
>
> As such, I'm trying to learn as few of the basics by going through and
> comverting smoe of the programs I made into Ruby. At the moment, I'm
> struggling a bit with the control structures, if-then-else is fine,
> switch/case is fine. I'm just a little confused about the for and
> while/dowhile loops.
>
> I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
> array of 'x' length and then fill it with random numbers, then check to
> see if those numbers are in order, if not, repeat the process. More or
> less anyway.
>
> At the moment I'm using this loop to fill the array:
> for num in (0..Integer(a))
> monkey[num]=Integer(rand*5+1)
> end
> variable 'a' is input by the user to determine how big a sequence, i.e.
> 5 numbers in a row.
>
> Is this the easiest way of doing things?
> And then I could use a similar loop to go through and check to see if
> each number is in order, but again, is there a simpler way to check?
>
> TJ
> --
> Posted via http://www.ruby-forum.com/.

monkey = []
a = gets

begin
0.upto(a.to_i) do |num|
monkey.push((rand*5+1).to_i)
end
end while a.sort != a

(Of course it is not the most time- and memory- effective way...)

Jakub Pavlik
--
Zatímco velbloud dvouhrbý má hrby dva, Dromedár má jen jeden.

Jorrel
Guest
Posts: n/a

 12-01-2008
> 0.upto(a.to_i) do |num|
> monkey.push((rand*5+1).to_i)
> end

or, since you're not using num anyway:
a.to_i.times { monkey.push((rand*5+1).to_i)

--
jorrel

Daniel Malcolm Webb [dbw]
Guest
Posts: n/a

 12-01-2008
Hi Jakub,

What would be the quickest way of doing it? (in terms of time and =
memory?)

Thanks,
Dan

-----Original Message-----
From: Jakub Pavl=EDk jn. [(E-Mail Removed)]=20
Sent: 01 December 2008 11:53
To: ruby-talk ML
Subject: Re: Control Structures

> G'day all, I'm new to Ruby, been studying Software Engineering at
> university and they have been teaching in Java.
>=20
> As such, I'm trying to learn as few of the basics by going through and
> comverting smoe of the programs I made into Ruby. At the moment, I'm
> struggling a bit with the control structures, if-then-else is fine,
> switch/case is fine. I'm just a little confused about the for and
> while/dowhile loops.
>=20
> I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
> array of 'x' length and then fill it with random numbers, then check =

to
> see if those numbers are in order, if not, repeat the process. More or
> less anyway.
>=20
> At the moment I'm using this loop to fill the array:
> for num in (0..Integer(a))
> monkey[num]=3DInteger(rand*5+1)
> end
> variable 'a' is input by the user to determine how big a sequence, =

i.e.
> 5 numbers in a row.
>=20
> Is this the easiest way of doing things?
> And then I could use a similar loop to go through and check to see if
> each number is in order, but again, is there a simpler way to check?
>=20
> TJ
> --=20
> Posted via http://www.ruby-forum.com/.

monkey =3D []
a =3D gets

begin
0.upto(a.to_i) do |num|
monkey.push((rand*5+1).to_i)
end
end while a.sort !=3D a

(Of course it is not the most time- and memory- effective way...)

Jakub Pavlik
--=20
Zat=EDmco velbloud dvouhrb=FD m=E1 hrby dva, Dromed=E1r m=E1 jen jeden.

Guest
Posts: n/a

 12-01-2008
[Note: parts of this message were removed to make it a legal post.]

See if this satisfies you:

while (arr = Array.new(4){rand 4}) != [0,1,2,4]
p arr
end
p arr

best wishes,

On Mon, Dec 1, 2008 at 5:07 PM, Trent Jones <(E-Mail Removed)> wrote:

> G'day all, I'm new to Ruby, been studying Software Engineering at
> university and they have been teaching in Java.
>
> As such, I'm trying to learn as few of the basics by going through and
> comverting smoe of the programs I made into Ruby. At the moment, I'm
> struggling a bit with the control structures, if-then-else is fine,
> switch/case is fine. I'm just a little confused about the for and
> while/dowhile loops.
>
> I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
> array of 'x' length and then fill it with random numbers, then check to
> see if those numbers are in order, if not, repeat the process. More or
> less anyway.
>
> At the moment I'm using this loop to fill the array:
> for num in (0..Integer(a))
> monkey[num]=Integer(rand*5+1)
> end
> variable 'a' is input by the user to determine how big a sequence, i.e.
> 5 numbers in a row.
>
> Is this the easiest way of doing things?
> And then I could use a similar loop to go through and check to see if
> each number is in order, but again, is there a simpler way to check?
>
> TJ
> --
> Posted via http://www.ruby-forum.com/.
>
>

Guest
Posts: n/a

 12-01-2008
[Note: parts of this message were removed to make it a legal post.]

sorry error: first line should be

while (arr = Array.new(4){rand 4}) != [0,1,2,3]

On Mon, Dec 1, 2008 at 6:08 PM, prasad <(E-Mail Removed)> wrote:

> See if this satisfies you:
>
> while (arr = Array.new(4){rand 4}) != [0,1,2,4]
> p arr
> end
> p arr
>
> best wishes,
>
>
>
> On Mon, Dec 1, 2008 at 5:07 PM, Trent Jones <(E-Mail Removed)> wrote:
>
>> G'day all, I'm new to Ruby, been studying Software Engineering at
>> university and they have been teaching in Java.
>>
>> As such, I'm trying to learn as few of the basics by going through and
>> comverting smoe of the programs I made into Ruby. At the moment, I'm
>> struggling a bit with the control structures, if-then-else is fine,
>> switch/case is fine. I'm just a little confused about the for and
>> while/dowhile loops.
>>
>> I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
>> array of 'x' length and then fill it with random numbers, then check to
>> see if those numbers are in order, if not, repeat the process. More or
>> less anyway.
>>
>> At the moment I'm using this loop to fill the array:
>> for num in (0..Integer(a))
>> monkey[num]=Integer(rand*5+1)
>> end
>> variable 'a' is input by the user to determine how big a sequence, i.e.
>> 5 numbers in a row.
>>
>> Is this the easiest way of doing things?
>> And then I could use a similar loop to go through and check to see if
>> each number is in order, but again, is there a simpler way to check?
>>
>> TJ
>> --
>> Posted via http://www.ruby-forum.com/.
>>
>>

>

Jakub Pavlík jn.
Guest
Posts: n/a

 12-01-2008
> Hi Jakub,
>
> What would be the quickest way of doing it? (in terms of time and memory?)
>
> Thanks,
> Dan
>
> -----Original Message-----
> From: Jakub Pavlík jn. [(E-Mail Removed)]
> Sent: 01 December 2008 11:53
> To: ruby-talk ML
> Subject: Re: Control Structures
>
> > G'day all, I'm new to Ruby, been studying Software Engineering at
> > university and they have been teaching in Java.
> >
> > As such, I'm trying to learn as few of the basics by going through and
> > comverting smoe of the programs I made into Ruby. At the moment, I'm
> > struggling a bit with the control structures, if-then-else is fine,
> > switch/case is fine. I'm just a little confused about the for and
> > while/dowhile loops.
> >
> > I'm trying to make a "infinite monkeys" simulation, i.e. initiate an
> > array of 'x' length and then fill it with random numbers, then check to
> > see if those numbers are in order, if not, repeat the process. More or
> > less anyway.
> >
> > At the moment I'm using this loop to fill the array:
> > for num in (0..Integer(a))
> > monkey[num]=Integer(rand*5+1)
> > end
> > variable 'a' is input by the user to determine how big a sequence, i.e.
> > 5 numbers in a row.
> >
> > Is this the easiest way of doing things?
> > And then I could use a similar loop to go through and check to see if
> > each number is in order, but again, is there a simpler way to check?
> >
> > TJ
> > --
> > Posted via http://www.ruby-forum.com/.

>
> monkey = []
> a = gets
>
> begin
> 0.upto(a.to_i) do |num|
> monkey.push((rand*5+1).to_i)
> end
> end while a.sort != a
>
> (Of course it is not the most time- and memory- effective way...)
>
> Jakub Pavlik
> --
> Zatímco velbloud dvouhrbý má hrby dva, Dromedár má jen jeden.
>
>

The following version doesn't use Array#sort (which returns sorted copy of Array; I haven't looked at Ruby source which sorting algorithm is used, you can look yourself if you want), but I presume that you don't need complete set of a numbers in every attempt. However it isn't hard to make another version without this presumption.

a = gets.to_i

loop do
ok = true

monkey = []

a.times do
n = (rand*5+1).to_i
if monkey.empty? || n >= monkey.last then
monkey.push n
else
ok = false
break
end
end

puts monkey.join(',')

break if ok
end

Brian Candler
Guest
Posts: n/a

 12-01-2008
Like many languages, there are lots of ways to do things. Using a block
with Array.new lets you initialise an Array with n elements in one go,
where the block is invoked n times to create each element.

I think that comparing monkey == monkey.sort is the easiest way to check
for values in sequence, but a more esoteric way is using
Enumerable#each_cons to check each pair in turn.

So this gives the following solution:

require 'enumerator'
puts "How many elements?"
a = Integer(gets)

loop do
monkey = Array.new(a) { rand(a) }
out_of_order = false
monkey.each_cons(2) { |x,y|
if x > y
out_of_order = true
break
end
}
puts "#{monkey.inspect}, out_of_order=#{out_of_order}"
end

Now, you can squeeze this a bit more, because each_cons normally returns
nil, but break can pass a different return value. This gives:

loop do
monkey = Array.new(a) { rand(a) }
out_of_order = monkey.each_cons(2) { |x,y|
break true if x > y
}
puts "#{monkey.inspect}, out_of_order=#{out_of_order ? "yes" : "no"}"
end

Now, to get really funky. The Enumerable module has a bunch of methods
for operating on sequences of objects which are yielded by the 'each'
method. Using to_enum you can insert a proxy object which maps the call
to #each to a call to another method - such as #each_cons. So then you
get:

loop do
monkey = Array.new(a) { rand(a) }
out_of_order = monkey.to_enum(:each_cons,2).find { |x,y| x > y }
puts "#{monkey.inspect} #{out_of_order && "bad monkey!"}"
end

I certainly wouldn't have written that as a newcomer to Ruby But
it's nice to know that, when you have mastered the basics, there's lots
more to chew on.

Regards,

Brian.

P.S. Try all this stuff in irb. For example, to try out each_cons:

irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> [1,2,3,4,5].each_cons(2) { |x| p x }
[1, 2]
[2, 3]
[3, 4]
[4, 5]
=> nil
--
Posted via http://www.ruby-forum.com/.

Robert Dober
Guest
Posts: n/a

 12-01-2008
I am not sure if you want this optimization

a = 3
m = a.times.inject([]){ |r,| x=rand(a); x < (r.last||0) && break; r <<
x } until m
or if you prefer
m = a.pred.times.inject( [rand( a )]){ |r,| x=rand(a); x < r.last &&
break; r << x } until m

now apart of not creating the full array when it is already unsorted
it is also a brain teaser to work all those new methods out, but that
is the beauty of Ruby.

P.S Ruby 1.8.7 needed works with PL 72 and 1.9 of course.

Cheers
Robert

Brian Candler
Guest
Posts: n/a

 12-01-2008
Robert Dober wrote:
> I am not sure if you want this optimization

Whilst this demonstrates Dober's Law that every program can be written
in the form of an inject statement, it doesn't necessarily mean that's
the best thing to do in every case
--
Posted via http://www.ruby-forum.com/.